Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions cli/args/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ pub struct Flags {
pub eszip: bool,
pub node_conditions: Vec<String>,
pub preload: Vec<String>,
pub require: Vec<String>,
pub tunnel: bool,
}

Expand Down Expand Up @@ -4016,6 +4017,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())
}

Expand Down Expand Up @@ -4606,6 +4608,15 @@ 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 (even if it's not with a .cjs or .tjs extension)")
.value_hint(ValueHint::FilePath)
}

fn min_dep_age_arg() -> Arg {
Arg::new("minimum-dependency-age")
.long("minimum-dependency-age")
Expand Down Expand Up @@ -6340,6 +6351,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(())
}
Expand Down Expand Up @@ -6618,6 +6630,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::<String>("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");
}
Expand Down Expand Up @@ -13279,6 +13297,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",
"-r",
"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 =
Expand Down
13 changes: 13 additions & 0 deletions cli/args/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,19 @@ impl CliOptions {
Ok(preload)
}

pub fn require_modules(&self) -> Result<Vec<ModuleSpecifier>, 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(
&self,
raw_specifier: &str,
Expand Down
1 change: 1 addition & 0 deletions cli/lib/standalone/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ pub struct Metadata {
pub workspace_resolver: SerializedWorkspaceResolver,
pub entrypoint_key: String,
pub preload_modules: Vec<String>,
pub require_modules: Vec<String>,
pub node_modules: Option<NodeModules>,
pub unstable_config: UnstableConfig,
pub otel_config: OtelConfig,
Expand Down
20 changes: 19 additions & 1 deletion cli/lib/worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -579,11 +579,13 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
permissions: PermissionsContainer,
main_module: Url,
preload_modules: Vec<Url>,
require_modules: Vec<Url>,
) -> Result<LibMainWorker, CoreError> {
self.create_custom_worker(
mode,
main_module,
preload_modules,
require_modules,
permissions,
vec![],
Default::default(),
Expand All @@ -598,6 +600,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
mode: WorkerExecutionMode,
main_module: Url,
preload_modules: Vec<Url>,
require_modules: Vec<Url>,
permissions: PermissionsContainer,
custom_extensions: Vec<Extension>,
stdio: deno_runtime::deno_io::Stdio,
Expand Down Expand Up @@ -716,6 +719,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
Ok(LibMainWorker {
main_module,
preload_modules,
require_modules,
worker,
})
}
Expand Down Expand Up @@ -803,6 +807,7 @@ impl<TSys: DenoLibSys> LibMainWorkerFactory<TSys> {
pub struct LibMainWorker {
main_module: Url,
preload_modules: Vec<Url>,
require_modules: Vec<Url>,
worker: MainWorker,
}

Expand Down Expand Up @@ -864,6 +869,16 @@ impl LibMainWorker {
self.worker.evaluate_module(id).await
}

pub async fn execute_require_modules(&mut self) -> Result<(), CoreError> {
for require_module_url in self.require_modules.iter() {
// Execute CommonJS modules using Node.js require
let id = self.worker.preload_side_module(require_module_url).await?;
Comment on lines +874 to +875
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is executing modules as ESM, not CommonJS - you will need to do it manually

self.worker.evaluate_module(id).await?;
self.worker.run_event_loop(false).await?;
}
Ok(())
}

pub async fn execute_preload_modules(&mut self) -> Result<(), CoreError> {
for preload_module_url in self.preload_modules.iter() {
let id = self.worker.preload_side_module(preload_module_url).await?;
Expand All @@ -876,7 +891,10 @@ impl LibMainWorker {
pub async fn run(&mut self) -> Result<i32, CoreError> {
log::debug!("main_module {}", self.main_module);

// Run preload modules first if they were defined
// Run require modules first if they were defined (CommonJS)
self.execute_require_modules().await?;

// Run preload modules (ES modules)
self.execute_preload_modules().await?;

self.execute_main_module().await?;
Expand Down
13 changes: 12 additions & 1 deletion cli/module_loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,7 @@ struct SharedCliModuleLoaderState {
sys: CliSys,
in_flight_loads_tracker: InFlightModuleLoadsTracker,
maybe_eszip_loader: Option<Arc<EszipModuleLoader>>,
require_modules: Arc<HashSet<ModuleSpecifier>>,
}

struct InFlightModuleLoadsTracker {
Expand Down Expand Up @@ -410,6 +411,8 @@ impl CliModuleLoaderFactory {
sys: CliSys,
maybe_eszip_loader: Option<Arc<EszipModuleLoader>>,
) -> Self {
let require_modules_list = options.require_modules().unwrap_or_default();

Self {
shared: Arc::new(SharedCliModuleLoaderState {
graph_kind: options.graph_kind(),
Expand Down Expand Up @@ -442,6 +445,9 @@ impl CliModuleLoaderFactory {
cleanup_task_handle: Arc::new(Mutex::new(None)),
},
maybe_eszip_loader,
require_modules: Arc::new(
require_modules_list.into_iter().collect::<HashSet<_>>(),
),
}),
}
}
Expand Down Expand Up @@ -578,9 +584,10 @@ impl<TGraphContainer: ModuleGraphContainer>
specifier: &ModuleSpecifier,
maybe_referrer: Option<&ModuleSpecifier>,
requested_module_type: &RequestedModuleType,
is_from_require: bool,
) -> Result<ModuleSource, ModuleLoaderError> {
let code_source = self
.load_code_source(specifier, maybe_referrer, requested_module_type)
.load_code_source(specifier, maybe_referrer, requested_module_type, is_from_require)
.await
.map_err(JsErrorBox::from_err)?;

Expand Down Expand Up @@ -632,6 +639,7 @@ impl<TGraphContainer: ModuleGraphContainer>
specifier: &ModuleSpecifier,
maybe_referrer: Option<&ModuleSpecifier>,
requested_module_type: &RequestedModuleType,
is_from_require: bool,
) -> Result<ModuleCodeStringSource, CliModuleLoaderError> {
// this loader maintains npm specifiers in dynamic imports when resolving
// so that they can be properly preloaded, but now we might receive them
Expand Down Expand Up @@ -674,6 +682,7 @@ impl<TGraphContainer: ModuleGraphContainer>
&specifier,
maybe_referrer,
&deno_resolver_requested_module_type,
is_from_require,
)
.await?
{
Expand Down Expand Up @@ -1026,13 +1035,15 @@ impl<TGraphContainer: ModuleGraphContainer> ModuleLoader

let specifier = specifier.clone();
let maybe_referrer = maybe_referrer.cloned();
let is_from_require = self.0.shared.require_modules.contains(&specifier);
deno_core::ModuleLoadResponse::Async(
async move {
inner
.load_inner(
&specifier,
maybe_referrer.as_ref().map(|r| &r.specifier),
&options.requested_module_type,
is_from_require,
)
.await
.map_err(|err| {
Expand Down
7 changes: 7 additions & 0 deletions cli/rt/run.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1082,11 +1082,18 @@ pub async fn run(
.map(|key| root_dir_url.join(key).unwrap())
.collect::<Vec<_>>();

let require_modules = metadata
.require_modules
.iter()
.map(|key| root_dir_url.join(key).unwrap())
.collect::<Vec<_>>();

let mut worker = worker_factory.create_main_worker(
WorkerExecutionMode::Run,
permissions,
main_module,
preload_modules,
require_modules,
)?;

let exit_code = worker.run().await?;
Expand Down
8 changes: 8 additions & 0 deletions cli/standalone/binary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,13 @@ impl<'a> DenoCompileBinaryWriter<'a> {
.map(|s| root_dir_url.specifier_key(&s).into_owned())
.collect::<Vec<_>>();

let require_modules = self
.cli_options
.require_modules()?
.into_iter()
.map(|s| root_dir_url.specifier_key(&s).into_owned())
.collect::<Vec<_>>();

let metadata = Metadata {
argv: compile_flags.args.clone(),
seed: self.cli_options.seed(),
Expand All @@ -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 {
Expand Down
1 change: 1 addition & 0 deletions cli/tools/bench/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,7 @@ async fn bench_specifier_inner(
WorkerExecutionMode::Bench,
specifier.clone(),
preload_modules,
vec![],
permissions_container,
vec![ops::bench::deno_bench::init(sender.clone())],
Default::default(),
Expand Down
2 changes: 1 addition & 1 deletion cli/tools/bundle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1367,7 +1367,7 @@ impl DenoPluginHandler {
let graph = self.module_graph_container.graph();
let module_or_asset = self
.module_loader
.load(&graph, &specifier, None, requested_type)
.load(&graph, &specifier, None, requested_type, false)
.await;
let module_or_asset = match module_or_asset {
Ok(module_or_asset) => module_or_asset,
Expand Down
1 change: 1 addition & 0 deletions cli/tools/deploy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub async fn deploy(mut flags: Flags) -> Result<i32, AnyError> {
WorkerExecutionMode::Deploy,
specifier,
vec![],
vec![],
PermissionsContainer::allow_all(
factory.permission_desc_parser()?.clone(),
),
Expand Down
1 change: 1 addition & 0 deletions cli/tools/jupyter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ pub async fn kernel(
main_module.clone(),
// `deno jupyter` doesn't support preloading modules
vec![],
vec![],
permissions,
vec![
ops::jupyter::deno_jupyter::init(stdio_tx.clone()),
Expand Down
1 change: 1 addition & 0 deletions cli/tools/lint/plugins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ async fn create_plugin_runner_inner(
main_module.clone(),
// `deno lint` doesn't support preloading modules
vec![],
vec![],
permissions,
vec![crate::ops::lint::deno_lint_ext::init(logger.clone())],
Default::default(),
Expand Down
1 change: 1 addition & 0 deletions cli/tools/repl/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ pub async fn run(
main_module.clone(),
// `deno repl` doesn't support preloading modules
vec![],
vec![],
permissions.clone(),
vec![crate::ops::testing::deno_test::init(test_event_sender)],
Default::default(),
Expand Down
Loading