mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat: load multiple eszips (#1)
This commit is contained in:
parent
deb67c9102
commit
2f179e4dfd
4 changed files with 74 additions and 37 deletions
|
@ -178,7 +178,7 @@ async fn run_subcommand(flags: Flags) -> Result<i32, AnyError> {
|
|||
if run_flags.is_stdin() {
|
||||
tools::run::run_from_stdin(flags).await
|
||||
} else if flags.eszip {
|
||||
tools::run::run_eszip(flags).await
|
||||
tools::run::run_eszip(flags, run_flags).await
|
||||
} else {
|
||||
tools::run::run_script(WorkerExecutionMode::Run, flags, run_flags.watch).await
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ fn main() {
|
|||
let image_name =
|
||||
current_exe_path.file_name().unwrap().to_string_lossy();
|
||||
let exit_code = standalone::run(
|
||||
eszip,
|
||||
vec![eszip],
|
||||
metadata,
|
||||
current_exe_path.as_os_str().as_encoded_bytes(),
|
||||
&image_name,
|
||||
|
|
|
@ -95,7 +95,7 @@ struct WorkspaceEszipModule {
|
|||
}
|
||||
|
||||
struct WorkspaceEszip {
|
||||
eszip: eszip::EszipV2,
|
||||
eszips: Vec<eszip::EszipV2>,
|
||||
root_dir_url: Arc<ModuleSpecifier>,
|
||||
}
|
||||
|
||||
|
@ -104,17 +104,28 @@ impl WorkspaceEszip {
|
|||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<WorkspaceEszipModule> {
|
||||
let lookup = |key: &str| {
|
||||
for (i, x) in self.eszips.iter().enumerate().rev() {
|
||||
println!("specifiers[{}]: {:?}", i, x.specifiers());
|
||||
if let Some(x) = x.get_module(key) {
|
||||
return Some(x);
|
||||
}
|
||||
}
|
||||
None
|
||||
};
|
||||
|
||||
if specifier.scheme() == "file" {
|
||||
let specifier_key = EszipRelativeFileBaseUrl::new(&self.root_dir_url)
|
||||
.specifier_key(specifier);
|
||||
let module = self.eszip.get_module(&specifier_key)?;
|
||||
println!("Trying file specifier key: {}", specifier_key);
|
||||
let module = lookup(&specifier_key)?;
|
||||
let specifier = self.root_dir_url.join(&module.specifier).unwrap();
|
||||
Some(WorkspaceEszipModule {
|
||||
specifier,
|
||||
inner: module,
|
||||
})
|
||||
} else {
|
||||
let module = self.eszip.get_module(specifier.as_str())?;
|
||||
let module = lookup(specifier.as_str())?;
|
||||
Some(WorkspaceEszipModule {
|
||||
specifier: ModuleSpecifier::parse(&module.specifier).unwrap(),
|
||||
inner: module,
|
||||
|
@ -329,7 +340,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
|
||||
let Some(module) = self.shared.eszip.get_module(original_specifier) else {
|
||||
return deno_core::ModuleLoadResponse::Sync(Err(type_error(format!(
|
||||
"Module not found: {}",
|
||||
"Module specifier not found: {}",
|
||||
original_specifier
|
||||
))));
|
||||
};
|
||||
|
@ -338,7 +349,10 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
deno_core::ModuleLoadResponse::Async(
|
||||
async move {
|
||||
let code = module.inner.source().await.ok_or_else(|| {
|
||||
type_error(format!("Module not found: {}", original_specifier))
|
||||
type_error(format!(
|
||||
"Module source is not available: {}",
|
||||
original_specifier
|
||||
))
|
||||
})?;
|
||||
let code = arc_u8_to_arc_str(code)
|
||||
.map_err(|_| type_error("Module source is not utf-8"))?;
|
||||
|
@ -349,9 +363,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
|||
eszip::ModuleKind::Jsonc => {
|
||||
return Err(type_error("jsonc modules not supported"))
|
||||
}
|
||||
eszip::ModuleKind::OpaqueData => {
|
||||
unreachable!();
|
||||
}
|
||||
eszip::ModuleKind::OpaqueData => ModuleType::JavaScript,
|
||||
},
|
||||
ModuleSourceCode::String(code.into()),
|
||||
&original_specifier,
|
||||
|
@ -429,11 +441,13 @@ impl RootCertStoreProvider for StandaloneRootCertStoreProvider {
|
|||
}
|
||||
|
||||
pub async fn run(
|
||||
mut eszip: eszip::EszipV2,
|
||||
mut eszips: Vec<eszip::EszipV2>,
|
||||
metadata: Metadata,
|
||||
image_path: &[u8],
|
||||
image_name: &str,
|
||||
) -> Result<i32, AnyError> {
|
||||
assert!(!eszips.is_empty());
|
||||
|
||||
let image_path_hash = Sha256::digest(image_path);
|
||||
let mut image_path_hash_buf = [0u8; 40];
|
||||
let image_path_hash = &*faster_hex::hex_encode(
|
||||
|
@ -470,7 +484,8 @@ pub async fn run(
|
|||
let (fs, npm_resolver, maybe_vfs_root) = match metadata.node_modules {
|
||||
Some(binary::NodeModules::Managed { node_modules_dir }) => {
|
||||
// this will always have a snapshot
|
||||
let snapshot = eszip.take_npm_snapshot().unwrap();
|
||||
// TODO: support npm modules in eszips other than the last one
|
||||
let snapshot = eszips.last_mut().unwrap().take_npm_snapshot().unwrap();
|
||||
let vfs_root_dir_path = if node_modules_dir.is_some() {
|
||||
root_path.clone()
|
||||
} else {
|
||||
|
@ -625,7 +640,7 @@ pub async fn run(
|
|||
let module_loader_factory = StandaloneModuleLoaderFactory {
|
||||
shared: Arc::new(SharedModuleLoaderState {
|
||||
eszip: WorkspaceEszip {
|
||||
eszip,
|
||||
eszips,
|
||||
root_dir_url,
|
||||
},
|
||||
workspace_resolver,
|
||||
|
|
|
@ -3,20 +3,22 @@
|
|||
use std::io::Read;
|
||||
|
||||
use deno_config::workspace::PackageJsonDepResolution;
|
||||
use deno_core::anyhow::bail;
|
||||
use deno_core::anyhow::Context;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::io::BufReader;
|
||||
use deno_core::futures::io::Cursor;
|
||||
use deno_core::futures::stream::FuturesOrdered;
|
||||
use deno_core::futures::StreamExt;
|
||||
use deno_core::unsync::spawn;
|
||||
use deno_runtime::deno_permissions::Permissions;
|
||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||
use deno_runtime::WorkerExecutionMode;
|
||||
use eszip::EszipV2;
|
||||
use tokio_util::compat::TokioAsyncReadCompatExt;
|
||||
|
||||
use crate::args::CaData;
|
||||
use crate::args::EvalFlags;
|
||||
use crate::args::Flags;
|
||||
use crate::args::RunFlags;
|
||||
use crate::args::WatchFlagsWithPaths;
|
||||
use crate::factory::CliFactory;
|
||||
use crate::factory::CliFactoryBuilder;
|
||||
|
@ -212,27 +214,50 @@ async fn maybe_npm_install(factory: &CliFactory) -> Result<(), AnyError> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn run_eszip(flags: Flags) -> Result<i32, AnyError> {
|
||||
pub async fn run_eszip(
|
||||
flags: Flags,
|
||||
run_flags: RunFlags,
|
||||
) -> Result<i32, AnyError> {
|
||||
// TODO(bartlomieju): actually I think it will also fail if there's an import
|
||||
// map specified and bare specifier is used on the command line
|
||||
let factory = CliFactory::from_flags(flags.clone())?;
|
||||
let cli_options = factory.cli_options();
|
||||
let file_fetcher = factory.file_fetcher()?;
|
||||
let permissions = PermissionsContainer::new(Permissions::from_options(
|
||||
&cli_options.permissions_options()?,
|
||||
)?);
|
||||
let main_module = cli_options.resolve_main_module()?;
|
||||
|
||||
// TODO: streaming load
|
||||
let eszip = file_fetcher.fetch(&main_module, &permissions).await?;
|
||||
let eszip = BufReader::new(Cursor::new(eszip.source));
|
||||
let (eszip, loader) = EszipV2::parse(eszip).await?;
|
||||
// entrypoint#path1,path2,...
|
||||
let (entrypoint, files) = run_flags
|
||||
.script
|
||||
.split_once("#")
|
||||
.with_context(|| "eszip: invalid script string")?;
|
||||
|
||||
println!("running eszip: entrypoint={} files={}", entrypoint, files);
|
||||
|
||||
// TODO: handle paths that contain ','
|
||||
let files = files.split(",").collect::<Vec<_>>();
|
||||
let mut headers = FuturesOrdered::new();
|
||||
for path in files {
|
||||
let file = tokio::fs::File::open(path).await?;
|
||||
let eszip = BufReader::new(file.compat());
|
||||
let path = path.to_string();
|
||||
|
||||
headers.push_back(async move {
|
||||
let (eszip, loader) = match EszipV2::parse(eszip).await {
|
||||
Ok(x) => x,
|
||||
Err(e) => {
|
||||
log::error!("Error parsing eszip header at {}: {}", path, e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
spawn(async move {
|
||||
if let Err(e) = loader.await {
|
||||
log::error!("Error loading ESZip: {}", e);
|
||||
log::error!("Error loading eszip at {}: {}", path, e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
});
|
||||
eszip
|
||||
});
|
||||
}
|
||||
let headers = headers.collect::<Vec<_>>().await;
|
||||
|
||||
let ca_data = match cli_options.ca_data() {
|
||||
Some(CaData::File(ca_file)) => Some(
|
||||
std::fs::read(ca_file).with_context(|| format!("Reading: {ca_file}"))?,
|
||||
|
@ -240,12 +265,9 @@ pub async fn run_eszip(flags: Flags) -> Result<i32, AnyError> {
|
|||
Some(CaData::Bytes(bytes)) => Some(bytes.clone()),
|
||||
None => None,
|
||||
};
|
||||
let Some(entrypoint_key) = eszip.specifiers().into_iter().next() else {
|
||||
bail!("No modules found in eszip");
|
||||
};
|
||||
|
||||
crate::standalone::run(
|
||||
eszip,
|
||||
headers,
|
||||
Metadata {
|
||||
argv: flags.argv,
|
||||
seed: flags.seed,
|
||||
|
@ -257,7 +279,7 @@ pub async fn run_eszip(flags: Flags) -> Result<i32, AnyError> {
|
|||
ca_data,
|
||||
unsafely_ignore_certificate_errors: flags
|
||||
.unsafely_ignore_certificate_errors,
|
||||
entrypoint_key,
|
||||
entrypoint_key: entrypoint.to_string(),
|
||||
node_modules: None,
|
||||
disable_deprecated_api_warning: false,
|
||||
unstable_config: flags.unstable_config,
|
||||
|
@ -268,7 +290,7 @@ pub async fn run_eszip(flags: Flags) -> Result<i32, AnyError> {
|
|||
pkg_json_resolution: PackageJsonDepResolution::Disabled,
|
||||
},
|
||||
},
|
||||
main_module.to_string().as_bytes(),
|
||||
run_flags.script.as_bytes(),
|
||||
"run-eszip",
|
||||
)
|
||||
.await
|
||||
|
|
Loading…
Reference in a new issue