diff options
author | Bartek IwaĆczuk <biwanczuk@gmail.com> | 2021-10-28 10:11:38 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-10-28 10:11:38 +0200 |
commit | f77c5701f774b5f0ba548fb1e0eb53dfd304f440 (patch) | |
tree | eb243ccce5516a8e2ed90484b94cb81b0f67ad1a /cli/compat/esm_resolver.rs | |
parent | a065604155991dbf4417b606d4562d275cd8955f (diff) |
feat(compat): integrate import map and classic resolutions in ESM resolution (#12549)
This commit integrates import map and "classic" resolutions in
the "--compat" mode when using ES modules; in effect
"http:", "https:" and "blob:" imports now work in compat mode.
The algorithm works as follows:
1. If there's an import map, try to resolve using it and if succeeded
return the specifier
2. Try to resolve using "Node ESM resolution", and if succeeded return
the specifier
3. Fall back to regular ESM resolution
Diffstat (limited to 'cli/compat/esm_resolver.rs')
-rw-r--r-- | cli/compat/esm_resolver.rs | 48 |
1 files changed, 44 insertions, 4 deletions
diff --git a/cli/compat/esm_resolver.rs b/cli/compat/esm_resolver.rs index a4ea8cffc..f069428e5 100644 --- a/cli/compat/esm_resolver.rs +++ b/cli/compat/esm_resolver.rs @@ -1,6 +1,7 @@ // Copyright 2018-2021 the Deno authors. All rights reserved. MIT license. use super::errors; +use crate::resolver::ImportMapResolver; use deno_core::error::generic_error; use deno_core::error::AnyError; use deno_core::serde_json; @@ -13,21 +14,60 @@ use regex::Regex; use std::path::PathBuf; #[derive(Debug, Default)] -pub struct NodeEsmResolver; +pub(crate) struct NodeEsmResolver<'a> { + maybe_import_map_resolver: Option<ImportMapResolver<'a>>, +} + +impl<'a> NodeEsmResolver<'a> { + pub fn new(maybe_import_map_resolver: Option<ImportMapResolver<'a>>) -> Self { + Self { + maybe_import_map_resolver, + } + } -impl NodeEsmResolver { pub fn as_resolver(&self) -> &dyn Resolver { self } } -impl Resolver for NodeEsmResolver { +impl Resolver for NodeEsmResolver<'_> { fn resolve( &self, specifier: &str, referrer: &ModuleSpecifier, ) -> Result<ModuleSpecifier, AnyError> { - node_resolve(specifier, referrer.as_str(), &std::env::current_dir()?) + // First try to resolve using import map, ignoring any errors + if !specifier.starts_with("node:") { + if let Some(import_map_resolver) = &self.maybe_import_map_resolver { + if let Ok(specifier) = import_map_resolver.resolve(specifier, referrer) + { + return Ok(specifier); + } + } + } + + let node_resolution = + node_resolve(specifier, referrer.as_str(), &std::env::current_dir()?); + + match node_resolution { + Ok(specifier) => { + // If node resolution succeeded, return the specifier + Ok(specifier) + } + Err(err) => { + // If node resolution failed, check if it's because of unsupported + // URL scheme, and if so try to resolve using regular resolution algorithm + if err + .to_string() + .starts_with("[ERR_UNSUPPORTED_ESM_URL_SCHEME]") + { + return deno_core::resolve_import(specifier, referrer.as_str()) + .map_err(|err| err.into()); + } + + Err(err) + } + } } } |