summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDivy Srivastava <dj.srivastava23@gmail.com>2022-02-24 18:58:00 +0530
committerGitHub <noreply@github.com>2022-02-24 18:58:00 +0530
commit03c55b497035001cba77b0ddd8b22f0f9c25190d (patch)
treee4fded4e37329d5e56a79e1a3f49e5030c611ccf
parent3e8180c793f1dd7437a497ffdb0cf7e919a9a5c3 (diff)
fix(compile): Support import maps (#13756)
-rw-r--r--cli/main.rs18
-rw-r--r--cli/standalone.rs34
-rw-r--r--cli/tests/integration/compile_tests.rs34
-rw-r--r--cli/tests/testdata/standalone_import_map.json5
-rw-r--r--cli/tests/testdata/standalone_import_map.ts1
-rw-r--r--cli/tools/standalone.rs35
6 files changed, 110 insertions, 17 deletions
diff --git a/cli/main.rs b/cli/main.rs
index 091c33b13..16f7d6b9b 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -396,19 +396,21 @@ async fn compile_command(
) -> Result<i32, AnyError> {
let debug = flags.log_level == Some(log::Level::Debug);
- let run_flags =
- tools::standalone::compile_to_runtime_flags(&flags, compile_flags.args)?;
+ let run_flags = tools::standalone::compile_to_runtime_flags(
+ &flags,
+ compile_flags.args.clone(),
+ )?;
let module_specifier = resolve_url_or_path(&compile_flags.source_file)?;
let ps = ProcState::build(Arc::new(flags)).await?;
let deno_dir = &ps.dir;
- let output = compile_flags.output.and_then(|output| {
- if fs_util::path_has_trailing_slash(&output) {
+ let output = compile_flags.output.as_ref().and_then(|output| {
+ if fs_util::path_has_trailing_slash(output) {
let infer_file_name = infer_name_from_url(&module_specifier).map(PathBuf::from)?;
Some(output.join(infer_file_name))
} else {
- Some(output)
+ Some(output.to_path_buf())
}
}).or_else(|| {
infer_name_from_url(&module_specifier).map(PathBuf::from)
@@ -423,6 +425,8 @@ async fn compile_command(
generic_error("There should only be one reference to ModuleGraph")
})?;
+ graph.valid().unwrap();
+
let eszip = eszip::EszipV2::from_graph(graph, Default::default())?;
info!(
@@ -441,7 +445,9 @@ async fn compile_command(
eszip,
module_specifier.clone(),
run_flags,
- )?;
+ ps,
+ )
+ .await?;
info!("{} {}", colors::green("Emit"), output.display());
diff --git a/cli/standalone.rs b/cli/standalone.rs
index 9fa210795..b7c026cec 100644
--- a/cli/standalone.rs
+++ b/cli/standalone.rs
@@ -6,6 +6,7 @@ use crate::flags::Flags;
use crate::ops;
use crate::proc_state::ProcState;
use crate::version;
+use crate::ImportMapResolver;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::type_error;
@@ -19,6 +20,7 @@ use deno_core::url::Url;
use deno_core::v8_set_flags;
use deno_core::ModuleLoader;
use deno_core::ModuleSpecifier;
+use deno_graph::source::Resolver;
use deno_runtime::deno_broadcast_channel::InMemoryBroadcastChannel;
use deno_runtime::deno_tls::create_default_root_cert_store;
use deno_runtime::deno_tls::rustls_pemfile;
@@ -28,6 +30,7 @@ use deno_runtime::permissions::PermissionsOptions;
use deno_runtime::worker::MainWorker;
use deno_runtime::worker::WorkerOptions;
use deno_runtime::BootstrapOptions;
+use import_map::parse_from_json;
use log::Level;
use std::env::current_exe;
use std::io::BufReader;
@@ -51,6 +54,7 @@ pub struct Metadata {
pub ca_stores: Option<Vec<String>>,
pub ca_data: Option<Vec<u8>>,
pub unsafely_ignore_certificate_errors: Option<Vec<String>>,
+ pub maybe_import_map: Option<(Url, String)>,
pub entrypoint: ModuleSpecifier,
}
@@ -119,17 +123,26 @@ fn u64_from_bytes(arr: &[u8]) -> Result<u64, AnyError> {
Ok(u64::from_be_bytes(*fixed_arr))
}
-struct EmbeddedModuleLoader(eszip::EszipV2);
+struct EmbeddedModuleLoader {
+ eszip: eszip::EszipV2,
+ maybe_import_map_resolver: Option<ImportMapResolver>,
+}
impl ModuleLoader for EmbeddedModuleLoader {
fn resolve(
&self,
specifier: &str,
- base: &str,
+ referrer: &str,
_is_main: bool,
) -> Result<ModuleSpecifier, AnyError> {
- let resolve = deno_core::resolve_import(specifier, base)?;
- Ok(resolve)
+ let referrer = deno_core::resolve_url_or_path(referrer).unwrap();
+ self.maybe_import_map_resolver.as_ref().map_or_else(
+ || {
+ deno_core::resolve_import(specifier, referrer.as_str())
+ .map_err(|err| err.into())
+ },
+ |r| r.resolve(specifier, &referrer).to_result(),
+ )
}
fn load(
@@ -143,7 +156,7 @@ impl ModuleLoader for EmbeddedModuleLoader {
let is_data_uri = get_source_from_data_url(&module_specifier).ok();
let module = self
- .0
+ .eszip
.get_module(module_specifier.as_str())
.ok_or_else(|| type_error("Module not found"));
@@ -208,7 +221,16 @@ pub async fn run(
let permissions = Permissions::from_options(&metadata.permissions);
let blob_store = BlobStore::default();
let broadcast_channel = InMemoryBroadcastChannel::default();
- let module_loader = Rc::new(EmbeddedModuleLoader(eszip));
+ let module_loader = Rc::new(EmbeddedModuleLoader {
+ eszip,
+ maybe_import_map_resolver: metadata.maybe_import_map.map(
+ |(base, source)| {
+ ImportMapResolver::new(Arc::new(
+ parse_from_json(&base, &source).unwrap().import_map,
+ ))
+ },
+ ),
+ });
let create_web_worker_cb = Arc::new(|_| {
todo!("Worker are currently not supported in standalone binaries");
});
diff --git a/cli/tests/integration/compile_tests.rs b/cli/tests/integration/compile_tests.rs
index dcbbf158b..fbe6ffcf5 100644
--- a/cli/tests/integration/compile_tests.rs
+++ b/cli/tests/integration/compile_tests.rs
@@ -451,6 +451,40 @@ fn standalone_runtime_flags() {
}
#[test]
+fn standalone_import_map() {
+ let dir = TempDir::new().expect("tempdir fail");
+ let exe = if cfg!(windows) {
+ dir.path().join("import_map.exe")
+ } else {
+ dir.path().join("import_map")
+ };
+ let output = util::deno_cmd()
+ .current_dir(util::testdata_path())
+ .arg("compile")
+ .arg("--unstable")
+ .arg("--allow-read")
+ .arg("--import-map")
+ .arg("standalone_import_map.json")
+ .arg("--output")
+ .arg(&exe)
+ .arg("./standalone_import_map.ts")
+ .stdout(std::process::Stdio::piped())
+ .spawn()
+ .unwrap()
+ .wait_with_output()
+ .unwrap();
+ assert!(output.status.success());
+ let output = Command::new(exe)
+ .stdout(std::process::Stdio::piped())
+ .stderr(std::process::Stdio::piped())
+ .spawn()
+ .unwrap()
+ .wait_with_output()
+ .unwrap();
+ assert!(output.status.success());
+}
+
+#[test]
// https://github.com/denoland/deno/issues/12670
fn skip_rebundle() {
let dir = TempDir::new().expect("tempdir fail");
diff --git a/cli/tests/testdata/standalone_import_map.json b/cli/tests/testdata/standalone_import_map.json
new file mode 100644
index 000000000..6f978d6be
--- /dev/null
+++ b/cli/tests/testdata/standalone_import_map.json
@@ -0,0 +1,5 @@
+{
+ "imports": {
+ "hello": "./001_hello.js"
+ }
+}
diff --git a/cli/tests/testdata/standalone_import_map.ts b/cli/tests/testdata/standalone_import_map.ts
new file mode 100644
index 000000000..097b96356
--- /dev/null
+++ b/cli/tests/testdata/standalone_import_map.ts
@@ -0,0 +1 @@
+import "hello";
diff --git a/cli/tools/standalone.rs b/cli/tools/standalone.rs
index 44150add8..8d574aec7 100644
--- a/cli/tools/standalone.rs
+++ b/cli/tools/standalone.rs
@@ -5,11 +5,17 @@ use crate::flags::CheckFlag;
use crate::flags::DenoSubcommand;
use crate::flags::Flags;
use crate::flags::RunFlags;
+use crate::standalone::Metadata;
+use crate::standalone::MAGIC_TRAILER;
+use crate::ProcState;
use deno_core::anyhow::bail;
+use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_core::serde_json;
+use deno_core::url::Url;
use deno_graph::ModuleSpecifier;
use deno_runtime::deno_fetch::reqwest::Client;
+use deno_runtime::permissions::Permissions;
use std::env;
use std::fs::read;
use std::fs::File;
@@ -20,9 +26,6 @@ use std::io::Write;
use std::path::Path;
use std::path::PathBuf;
-use crate::standalone::Metadata;
-use crate::standalone::MAGIC_TRAILER;
-
pub async fn get_base_binary(
deno_dir: &DenoDir,
target: Option<String>,
@@ -85,11 +88,12 @@ async fn download_base_binary(
/// This functions creates a standalone deno binary by appending a bundle
/// and magic trailer to the currently executing binary.
-pub fn create_standalone_binary(
+pub async fn create_standalone_binary(
mut original_bin: Vec<u8>,
eszip: eszip::EszipV2,
entrypoint: ModuleSpecifier,
flags: Flags,
+ ps: ProcState,
) -> Result<Vec<u8>, AnyError> {
let mut eszip_archive = eszip.into_bytes();
@@ -97,6 +101,26 @@ pub fn create_standalone_binary(
Some(ca_file) => Some(read(ca_file)?),
None => None,
};
+ let maybe_import_map: Option<(Url, String)> = match flags
+ .import_map_path
+ .as_ref()
+ {
+ None => None,
+ Some(import_map_url) => {
+ let import_map_specifier = deno_core::resolve_url_or_path(import_map_url)
+ .context(format!("Bad URL (\"{}\") for import map.", import_map_url))?;
+ let file = ps
+ .file_fetcher
+ .fetch(&import_map_specifier, &mut Permissions::allow_all())
+ .await
+ .context(format!(
+ "Unable to load '{}' import map",
+ import_map_specifier
+ ))?;
+
+ Some((import_map_specifier, file.source.to_string()))
+ }
+ };
let metadata = Metadata {
argv: flags.argv.clone(),
unstable: flags.unstable,
@@ -111,6 +135,7 @@ pub fn create_standalone_binary(
ca_stores: flags.ca_stores,
ca_data,
entrypoint,
+ maybe_import_map,
};
let mut metadata = serde_json::to_string(&metadata)?.as_bytes().to_vec();
@@ -233,7 +258,7 @@ pub fn compile_to_runtime_flags(
coverage_dir: flags.coverage_dir.clone(),
enable_testing_features: false,
ignore: vec![],
- import_map_path: None,
+ import_map_path: flags.import_map_path.clone(),
inspect_brk: None,
inspect: None,
location: flags.location.clone(),