Skip to main content
Module

x/deno/cli/worker.rs

A modern runtime for JavaScript and TypeScript.
Go to Latest
File
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use std::path::PathBuf;use std::rc::Rc;use std::sync::Arc;
use deno_ast::ModuleSpecifier;use deno_core::error::AnyError;use deno_core::futures::task::LocalFutureObj;use deno_core::futures::FutureExt;use deno_core::located_script_name;use deno_core::serde_json::json;use deno_core::serde_v8;use deno_core::v8;use deno_core::Extension;use deno_core::ModuleId;use deno_runtime::colors;use deno_runtime::fmt_errors::format_js_error;use deno_runtime::ops::worker_host::CreateWebWorkerCb;use deno_runtime::ops::worker_host::WorkerEventCb;use deno_runtime::permissions::PermissionsContainer;use deno_runtime::web_worker::WebWorker;use deno_runtime::web_worker::WebWorkerOptions;use deno_runtime::worker::MainWorker;use deno_runtime::worker::WorkerOptions;use deno_runtime::BootstrapOptions;
use crate::args::DenoSubcommand;use crate::errors;use crate::module_loader::CliModuleLoader;use crate::node;use crate::npm::NpmPackageReference;use crate::ops;use crate::proc_state::ProcState;use crate::tools;use crate::tools::coverage::CoverageCollector;use crate::tools::test::TestMode;use crate::util::checksum;use crate::version;
pub struct CliMainWorker { main_module: ModuleSpecifier, is_main_cjs: bool, worker: MainWorker, ps: ProcState,
js_run_tests_callback: Option<v8::Global<v8::Function>>, js_run_benchmarks_callback: Option<v8::Global<v8::Function>>, js_enable_test_callback: Option<v8::Global<v8::Function>>, js_enable_bench_callback: Option<v8::Global<v8::Function>>,}
impl CliMainWorker { pub fn into_main_worker(self) -> MainWorker { self.worker }
pub async fn setup_repl(&mut self) -> Result<(), AnyError> { self.worker.run_event_loop(false).await?; Ok(()) }
pub async fn run(&mut self) -> Result<i32, AnyError> { let mut maybe_coverage_collector = self.maybe_setup_coverage_collector().await?; log::debug!("main_module {}", self.main_module);
if self.is_main_cjs { self.ps.prepare_node_std_graph().await?; self.initialize_main_module_for_node().await?; node::load_cjs_module_from_ext_node( &mut self.worker.js_runtime, &self.main_module.to_file_path().unwrap().to_string_lossy(), true, self.ps.options.inspect_brk().is_some(), )?; } else { self.execute_main_module_possibly_with_npm().await?; }
self.worker.dispatch_load_event(&located_script_name!())?;
loop { self .worker .run_event_loop(maybe_coverage_collector.is_none()) .await?; if !self .worker .dispatch_beforeunload_event(&located_script_name!())? { break; } }
self.worker.dispatch_unload_event(&located_script_name!())?;
if let Some(coverage_collector) = maybe_coverage_collector.as_mut() { self .worker .with_event_loop(coverage_collector.stop_collecting().boxed_local()) .await?; }
Ok(self.worker.exit_code()) }
pub async fn run_for_watcher(self) -> Result<(), AnyError> { /// The FileWatcherModuleExecutor provides module execution with safe dispatching of life-cycle events by tracking the /// state of any pending events and emitting accordingly on drop in the case of a future /// cancellation. struct FileWatcherModuleExecutor { inner: CliMainWorker, pending_unload: bool, }
impl FileWatcherModuleExecutor { pub fn new(worker: CliMainWorker) -> FileWatcherModuleExecutor { FileWatcherModuleExecutor { inner: worker, pending_unload: false, } }
/// Execute the given main module emitting load and unload events before and after execution /// respectively. pub async fn execute(&mut self) -> Result<(), AnyError> { self.inner.execute_main_module_possibly_with_npm().await?; self .inner .worker .dispatch_load_event(&located_script_name!())?; self.pending_unload = true;
let result = loop { match self.inner.worker.run_event_loop(false).await { Ok(()) => {} Err(error) => break Err(error), } match self .inner .worker .dispatch_beforeunload_event(&located_script_name!()) { Ok(default_prevented) if default_prevented => {} // continue loop Ok(_) => break Ok(()), Err(error) => break Err(error), } }; self.pending_unload = false;
result?;
self .inner .worker .dispatch_unload_event(&located_script_name!())?;
Ok(()) } }
impl Drop for FileWatcherModuleExecutor { fn drop(&mut self) { if self.pending_unload { let _ = self .inner .worker .dispatch_unload_event(&located_script_name!()); } } }
let mut executor = FileWatcherModuleExecutor::new(self); executor.execute().await }
pub async fn run_test_specifier( &mut self, mode: TestMode, ) -> Result<(), AnyError> { self.enable_test();
// Enable op call tracing in core to enable better debugging of op sanitizer // failures. if self.ps.options.trace_ops() { self .worker .js_runtime .execute_script( &located_script_name!(), "Deno.core.enableOpCallTracing();", ) .unwrap(); }
let mut maybe_coverage_collector = self.maybe_setup_coverage_collector().await?;
// We only execute the specifier as a module if it is tagged with TestMode::Module or // TestMode::Both. if mode != TestMode::Documentation { // We execute the module module as a side module so that import.meta.main is not set. self.execute_side_module_possibly_with_npm().await?; }
self.worker.dispatch_load_event(&located_script_name!())?; self.run_tests(&self.ps.options.shuffle_tests()).await?; loop { if !self .worker .dispatch_beforeunload_event(&located_script_name!())? { break; } self.worker.run_event_loop(false).await?; }
self.worker.dispatch_unload_event(&located_script_name!())?;
if let Some(coverage_collector) = maybe_coverage_collector.as_mut() { self .worker .with_event_loop(coverage_collector.stop_collecting().boxed_local()) .await?; } Ok(()) }
pub async fn run_lsp_test_specifier( &mut self, mode: TestMode, ) -> Result<(), AnyError> { self.enable_test();
self .worker .execute_script( &located_script_name!(), "Deno.core.enableOpCallTracing();", ) .unwrap();
if mode != TestMode::Documentation { // We execute the module module as a side module so that import.meta.main is not set. self.execute_side_module_possibly_with_npm().await?; }
self.worker.dispatch_load_event(&located_script_name!())?; self.run_tests(&None).await?; loop { if !self .worker .dispatch_beforeunload_event(&located_script_name!())? { break; } self.worker.run_event_loop(false).await?; } self.worker.dispatch_unload_event(&located_script_name!())?; Ok(()) }
pub async fn run_bench_specifier(&mut self) -> Result<(), AnyError> { self.enable_bench();
// We execute the module module as a side module so that import.meta.main is not set. self.execute_side_module_possibly_with_npm().await?;
self.worker.dispatch_load_event(&located_script_name!())?; self.run_benchmarks().await?; loop { if !self .worker .dispatch_beforeunload_event(&located_script_name!())? { break; } self.worker.run_event_loop(false).await?; } self.worker.dispatch_unload_event(&located_script_name!())?; Ok(()) }
async fn execute_main_module_possibly_with_npm( &mut self, ) -> Result<(), AnyError> { if self.ps.npm_resolver.has_packages() { self.ps.prepare_node_std_graph().await?; } let id = self.worker.preload_main_module(&self.main_module).await?; self.evaluate_module_possibly_with_npm(id).await }
async fn execute_side_module_possibly_with_npm( &mut self, ) -> Result<(), AnyError> { let id = self.worker.preload_side_module(&self.main_module).await?; self.evaluate_module_possibly_with_npm(id).await }
async fn evaluate_module_possibly_with_npm( &mut self, id: ModuleId, ) -> Result<(), AnyError> { if self.ps.npm_resolver.has_packages() { self.initialize_main_module_for_node().await?; } self.worker.evaluate_module(id).await }
async fn initialize_main_module_for_node(&mut self) -> Result<(), AnyError> { self.ps.prepare_node_std_graph().await?; node::initialize_runtime( &mut self.worker.js_runtime, self.ps.options.node_modules_dir(), ) .await?; if let DenoSubcommand::Run(flags) = self.ps.options.sub_command() { if let Ok(pkg_ref) = NpmPackageReference::from_str(&flags.script) { // if the user ran a binary command, we'll need to set process.argv[0] // to be the name of the binary command instead of deno let binary_name = pkg_ref .sub_path .as_deref() .unwrap_or(pkg_ref.req.name.as_str()); node::initialize_binary_command( &mut self.worker.js_runtime, binary_name, ) .await?; } } Ok(()) }
async fn maybe_setup_coverage_collector( &mut self, ) -> Result<Option<CoverageCollector>, AnyError> { if let Some(ref coverage_dir) = self.ps.options.coverage_dir() { let session = self.worker.create_inspector_session().await;
let coverage_dir = PathBuf::from(coverage_dir); let mut coverage_collector = tools::coverage::CoverageCollector::new(coverage_dir, session); self .worker .with_event_loop(coverage_collector.start_collecting().boxed_local()) .await?; Ok(Some(coverage_collector)) } else { Ok(None) } }
/// Run tests declared with `Deno.test()`. Test events will be dispatched /// by calling ops which are currently only implemented in the CLI crate. pub async fn run_tests( &mut self, shuffle: &Option<u64>, ) -> Result<(), AnyError> { let promise = { let scope = &mut self.worker.js_runtime.handle_scope(); let cb = self.js_run_tests_callback.as_ref().unwrap().open(scope); let this = v8::undefined(scope).into(); let options = serde_v8::to_v8(scope, json!({ "shuffle": shuffle })).unwrap(); let promise = cb.call(scope, this, &[options]).unwrap(); v8::Global::new(scope, promise) }; self.worker.js_runtime.resolve_value(promise).await?; Ok(()) }
/// Run benches declared with `Deno.bench()`. Bench events will be dispatched /// by calling ops which are currently only implemented in the CLI crate. pub async fn run_benchmarks(&mut self) -> Result<(), AnyError> { let promise = { let scope = &mut self.worker.js_runtime.handle_scope(); let cb = self .js_run_benchmarks_callback .as_ref() .unwrap() .open(scope); let this = v8::undefined(scope).into(); let promise = cb.call(scope, this, &[]).unwrap(); v8::Global::new(scope, promise) }; self.worker.js_runtime.resolve_value(promise).await?; Ok(()) }
/// Enable `Deno.test()`. If this isn't called before executing user code, /// `Deno.test()` calls will noop. pub fn enable_test(&mut self) { let scope = &mut self.worker.js_runtime.handle_scope(); let cb = self.js_enable_test_callback.as_ref().unwrap().open(scope); let this = v8::undefined(scope).into(); cb.call(scope, this, &[]).unwrap(); }
/// Enable `Deno.bench()`. If this isn't called before executing user code, /// `Deno.bench()` calls will noop. pub fn enable_bench(&mut self) { let scope = &mut self.worker.js_runtime.handle_scope(); let cb = self.js_enable_bench_callback.as_ref().unwrap().open(scope); let this = v8::undefined(scope).into(); cb.call(scope, this, &[]).unwrap(); }}
pub async fn create_main_worker( ps: &ProcState, main_module: ModuleSpecifier, permissions: PermissionsContainer,) -> Result<CliMainWorker, AnyError> { create_main_worker_internal( ps, main_module, permissions, vec![], Default::default(), false, ) .await}
pub async fn create_main_worker_for_test_or_bench( ps: &ProcState, main_module: ModuleSpecifier, permissions: PermissionsContainer, custom_extensions: Vec<Extension>, stdio: deno_runtime::ops::io::Stdio,) -> Result<CliMainWorker, AnyError> { create_main_worker_internal( ps, main_module, permissions, custom_extensions, stdio, true, ) .await}
async fn create_main_worker_internal( ps: &ProcState, main_module: ModuleSpecifier, permissions: PermissionsContainer, mut custom_extensions: Vec<Extension>, stdio: deno_runtime::ops::io::Stdio, bench_or_test: bool,) -> Result<CliMainWorker, AnyError> { let (main_module, is_main_cjs) = if let Ok(package_ref) = NpmPackageReference::from_specifier(&main_module) { ps.npm_resolver .add_package_reqs(vec![package_ref.req.clone()]) .await?; let node_resolution = node::node_resolve_binary_export( &package_ref.req, package_ref.sub_path.as_deref(), &ps.npm_resolver, &mut PermissionsContainer::allow_all(), )?; let is_main_cjs = matches!(node_resolution, node::NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else if ps.npm_resolver.is_npm_main() { let node_resolution = node::url_to_node_resolution(main_module, &ps.npm_resolver)?; let is_main_cjs = matches!(node_resolution, node::NodeResolution::CommonJs(_)); (node_resolution.into_url(), is_main_cjs) } else { (main_module, false) };
let module_loader = CliModuleLoader::new( ps.clone(), PermissionsContainer::allow_all(), permissions.clone(), );
let maybe_inspector_server = ps.maybe_inspector_server.clone();
let create_web_worker_cb = create_web_worker_callback(ps.clone(), stdio.clone()); let web_worker_preload_module_cb = create_web_worker_preload_module_callback(ps.clone()); let web_worker_pre_execute_module_cb = create_web_worker_pre_execute_module_callback(ps.clone());
let maybe_storage_key = ps.options.resolve_storage_key(&main_module); let origin_storage_dir = maybe_storage_key.as_ref().map(|key| { ps.dir .origin_data_folder_path() .join(checksum::gen(&[key.as_bytes()])) }); let cache_storage_dir = maybe_storage_key.map(|key| { // TODO(@satyarohith): storage quota management // Note: we currently use temp_dir() to avoid managing storage size. std::env::temp_dir() .join("deno_cache") .join(checksum::gen(&[key.as_bytes()])) });
let mut extensions = ops::cli_exts(ps.clone()); extensions.append(&mut custom_extensions);
let options = WorkerOptions { bootstrap: BootstrapOptions { args: ps.options.argv().clone(), cpu_count: std::thread::available_parallelism() .map(|p| p.get()) .unwrap_or(1), debug_flag: ps .options .log_level() .map_or(false, |l| l == log::Level::Debug), enable_testing_features: ps.options.enable_testing_features(), locale: deno_core::v8::icu::get_language_tag(), location: ps.options.location_flag().clone(), no_color: !colors::use_color(), is_tty: colors::is_tty(), runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), unstable: ps.options.unstable(), user_agent: version::get_user_agent(), inspect: ps.options.is_inspecting(), }, extensions, extensions_with_js: vec![], startup_snapshot: Some(crate::js::deno_isolate_init()), unsafely_ignore_certificate_errors: ps .options .unsafely_ignore_certificate_errors() .clone(), root_cert_store: Some(ps.root_cert_store.clone()), seed: ps.options.seed(), source_map_getter: Some(Box::new(module_loader.clone())), format_js_error_fn: Some(Arc::new(format_js_error)), create_web_worker_cb, web_worker_preload_module_cb, web_worker_pre_execute_module_cb, maybe_inspector_server, should_break_on_first_statement: ps.options.inspect_brk().is_some(), should_wait_for_inspector_session: ps.options.inspect_wait().is_some(), module_loader, npm_resolver: Some(Rc::new(ps.npm_resolver.clone())), get_error_class_fn: Some(&errors::get_error_class_name), cache_storage_dir, origin_storage_dir, blob_store: ps.blob_store.clone(), broadcast_channel: ps.broadcast_channel.clone(), shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()), stdio, };
let mut worker = MainWorker::bootstrap_from_options( main_module.clone(), permissions, options, );
let ( js_run_tests_callback, js_run_benchmarks_callback, js_enable_test_callback, js_enable_bench_callback, ) = if bench_or_test { let scope = &mut worker.js_runtime.handle_scope(); let js_run_tests_callback = deno_core::JsRuntime::eval::<v8::Function>( scope, "Deno[Deno.internal].testing.runTests", ) .unwrap(); let js_run_benchmarks_callback = deno_core::JsRuntime::eval::<v8::Function>( scope, "Deno[Deno.internal].testing.runBenchmarks", ) .unwrap(); let js_enable_tests_callback = deno_core::JsRuntime::eval::<v8::Function>( scope, "Deno[Deno.internal].testing.enableTest", ) .unwrap(); let js_enable_bench_callback = deno_core::JsRuntime::eval::<v8::Function>( scope, "Deno[Deno.internal].testing.enableBench", ) .unwrap(); ( Some(v8::Global::new(scope, js_run_tests_callback)), Some(v8::Global::new(scope, js_run_benchmarks_callback)), Some(v8::Global::new(scope, js_enable_tests_callback)), Some(v8::Global::new(scope, js_enable_bench_callback)), ) } else { (None, None, None, None) };
Ok(CliMainWorker { main_module, is_main_cjs, worker, ps: ps.clone(), js_run_tests_callback, js_run_benchmarks_callback, js_enable_test_callback, js_enable_bench_callback, })}
// TODO(bartlomieju): this callback could have default value// and not be requiredfn create_web_worker_preload_module_callback( _ps: ProcState,) -> Arc<WorkerEventCb> { Arc::new(move |worker| { let fut = async move { Ok(worker) }; LocalFutureObj::new(Box::new(fut)) })}
fn create_web_worker_pre_execute_module_callback( ps: ProcState,) -> Arc<WorkerEventCb> { Arc::new(move |mut worker| { let ps = ps.clone(); let fut = async move { // this will be up to date after pre-load if ps.npm_resolver.has_packages() { node::initialize_runtime( &mut worker.js_runtime, ps.options.node_modules_dir(), ) .await?; }
Ok(worker) }; LocalFutureObj::new(Box::new(fut)) })}
fn create_web_worker_callback( ps: ProcState, stdio: deno_runtime::ops::io::Stdio,) -> Arc<CreateWebWorkerCb> { Arc::new(move |args| { let maybe_inspector_server = ps.maybe_inspector_server.clone();
let module_loader = CliModuleLoader::new_for_worker( ps.clone(), args.parent_permissions.clone(), args.permissions.clone(), ); let create_web_worker_cb = create_web_worker_callback(ps.clone(), stdio.clone()); let preload_module_cb = create_web_worker_preload_module_callback(ps.clone()); let pre_execute_module_cb = create_web_worker_pre_execute_module_callback(ps.clone());
let extensions = ops::cli_exts(ps.clone());
let maybe_storage_key = ps.options.resolve_storage_key(&args.main_module); let cache_storage_dir = maybe_storage_key.map(|key| { // TODO(@satyarohith): storage quota management // Note: we currently use temp_dir() to avoid managing storage size. std::env::temp_dir() .join("deno_cache") .join(checksum::gen(&[key.as_bytes()])) });
let options = WebWorkerOptions { bootstrap: BootstrapOptions { args: ps.options.argv().clone(), cpu_count: std::thread::available_parallelism() .map(|p| p.get()) .unwrap_or(1), debug_flag: ps .options .log_level() .map_or(false, |l| l == log::Level::Debug), enable_testing_features: ps.options.enable_testing_features(), locale: deno_core::v8::icu::get_language_tag(), location: Some(args.main_module.clone()), no_color: !colors::use_color(), is_tty: colors::is_tty(), runtime_version: version::deno(), ts_version: version::TYPESCRIPT.to_string(), unstable: ps.options.unstable(), user_agent: version::get_user_agent(), inspect: ps.options.is_inspecting(), }, extensions, startup_snapshot: Some(crate::js::deno_isolate_init()), unsafely_ignore_certificate_errors: ps .options .unsafely_ignore_certificate_errors() .clone(), root_cert_store: Some(ps.root_cert_store.clone()), seed: ps.options.seed(), create_web_worker_cb, preload_module_cb, pre_execute_module_cb, format_js_error_fn: Some(Arc::new(format_js_error)), source_map_getter: Some(Box::new(module_loader.clone())), module_loader, npm_resolver: Some(Rc::new(ps.npm_resolver.clone())), worker_type: args.worker_type, maybe_inspector_server, get_error_class_fn: Some(&errors::get_error_class_name), blob_store: ps.blob_store.clone(), broadcast_channel: ps.broadcast_channel.clone(), shared_array_buffer_store: Some(ps.shared_array_buffer_store.clone()), compiled_wasm_module_store: Some(ps.compiled_wasm_module_store.clone()), stdio: stdio.clone(), cache_storage_dir, };
WebWorker::bootstrap_from_options( args.name, args.permissions, args.main_module, args.worker_id, options, ) })}
#[cfg(test)]mod tests { use super::*; use deno_core::{resolve_url_or_path, FsModuleLoader}; use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel; use deno_runtime::deno_web::BlobStore; use deno_runtime::permissions::Permissions;
fn create_test_worker() -> MainWorker { let main_module = resolve_url_or_path("./hello.js").unwrap(); let permissions = PermissionsContainer::new(Permissions::default());
let options = WorkerOptions { bootstrap: BootstrapOptions { args: vec![], cpu_count: 1, debug_flag: false, enable_testing_features: false, locale: deno_core::v8::icu::get_language_tag(), location: None, no_color: true, is_tty: false, runtime_version: "x".to_string(), ts_version: "x".to_string(), unstable: false, user_agent: "x".to_string(), inspect: false, }, extensions: vec![], extensions_with_js: vec![], startup_snapshot: Some(crate::js::deno_isolate_init()), unsafely_ignore_certificate_errors: None, root_cert_store: None, seed: None, format_js_error_fn: None, source_map_getter: None, web_worker_preload_module_cb: Arc::new(|_| unreachable!()), web_worker_pre_execute_module_cb: Arc::new(|_| unreachable!()), create_web_worker_cb: Arc::new(|_| unreachable!()), maybe_inspector_server: None, should_break_on_first_statement: false, should_wait_for_inspector_session: false, module_loader: Rc::new(FsModuleLoader), npm_resolver: None, get_error_class_fn: None, cache_storage_dir: None, origin_storage_dir: None, blob_store: BlobStore::default(), broadcast_channel: InMemoryBroadcastChannel::default(), shared_array_buffer_store: None, compiled_wasm_module_store: None, stdio: Default::default(), };
MainWorker::bootstrap_from_options(main_module, permissions, options) }
#[tokio::test] async fn execute_mod_esm_imports_a() { let p = test_util::testdata_path().join("runtime/esm_imports_a.js"); let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap(); let mut worker = create_test_worker(); let result = worker.execute_main_module(&module_specifier).await; if let Err(err) = result { eprintln!("execute_mod err {:?}", err); } if let Err(e) = worker.run_event_loop(false).await { panic!("Future got unexpected error: {:?}", e); } }
#[tokio::test] async fn execute_mod_circular() { let p = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .unwrap() .join("tests/circular1.js"); let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap(); let mut worker = create_test_worker(); let result = worker.execute_main_module(&module_specifier).await; if let Err(err) = result { eprintln!("execute_mod err {:?}", err); } if let Err(e) = worker.run_event_loop(false).await { panic!("Future got unexpected error: {:?}", e); } }
#[tokio::test] async fn execute_mod_resolve_error() { // "foo" is not a valid module specifier so this should return an error. let mut worker = create_test_worker(); let module_specifier = resolve_url_or_path("does-not-exist").unwrap(); let result = worker.execute_main_module(&module_specifier).await; assert!(result.is_err()); }
#[tokio::test] async fn execute_mod_002_hello() { // This assumes cwd is project root (an assumption made throughout the // tests). let mut worker = create_test_worker(); let p = test_util::testdata_path().join("run/001_hello.js"); let module_specifier = resolve_url_or_path(&p.to_string_lossy()).unwrap(); let result = worker.execute_main_module(&module_specifier).await; assert!(result.is_ok()); }}