mirror of
https://github.com/denoland/deno.git
synced 2025-09-27 12:49:10 +00:00
fix(unstable): support importing files in npm packages as bytes and text (#30065)
This commit is contained in:
parent
a046f2c1bf
commit
cf441584a4
19 changed files with 545 additions and 349 deletions
|
@ -18,7 +18,6 @@ use deno_error::JsErrorBox;
|
||||||
use deno_lib::args::CaData;
|
use deno_lib::args::CaData;
|
||||||
use deno_lib::args::get_root_cert_store;
|
use deno_lib::args::get_root_cert_store;
|
||||||
use deno_lib::args::npm_process_state;
|
use deno_lib::args::npm_process_state;
|
||||||
use deno_lib::loader::NpmModuleLoader;
|
|
||||||
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
||||||
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
|
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
|
||||||
use deno_lib::npm::create_npm_process_state_provider;
|
use deno_lib::npm::create_npm_process_state_provider;
|
||||||
|
@ -915,7 +914,6 @@ impl CliFactory {
|
||||||
let in_npm_pkg_checker = self.in_npm_pkg_checker()?;
|
let in_npm_pkg_checker = self.in_npm_pkg_checker()?;
|
||||||
let workspace_factory = self.workspace_factory()?;
|
let workspace_factory = self.workspace_factory()?;
|
||||||
let resolver_factory = self.resolver_factory()?;
|
let resolver_factory = self.resolver_factory()?;
|
||||||
let node_code_translator = resolver_factory.node_code_translator()?;
|
|
||||||
let cjs_tracker = self.cjs_tracker()?.clone();
|
let cjs_tracker = self.cjs_tracker()?.clone();
|
||||||
let npm_registry_permission_checker = {
|
let npm_registry_permission_checker = {
|
||||||
let mode = if resolver_factory.use_byonm()? {
|
let mode = if resolver_factory.use_byonm()? {
|
||||||
|
@ -949,11 +947,7 @@ impl CliFactory {
|
||||||
in_npm_pkg_checker.clone(),
|
in_npm_pkg_checker.clone(),
|
||||||
self.main_module_graph_container().await?.clone(),
|
self.main_module_graph_container().await?.clone(),
|
||||||
self.module_load_preparer().await?.clone(),
|
self.module_load_preparer().await?.clone(),
|
||||||
NpmModuleLoader::new(
|
resolver_factory.npm_module_loader()?.clone(),
|
||||||
self.cjs_tracker()?.clone(),
|
|
||||||
node_code_translator.clone(),
|
|
||||||
self.sys(),
|
|
||||||
),
|
|
||||||
npm_registry_permission_checker,
|
npm_registry_permission_checker,
|
||||||
cli_npm_resolver.clone(),
|
cli_npm_resolver.clone(),
|
||||||
resolver_factory.parsed_source_cache().clone(),
|
resolver_factory.parsed_source_cache().clone(),
|
||||||
|
|
|
@ -1,228 +1,75 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::path::PathBuf;
|
|
||||||
use std::sync::Arc;
|
|
||||||
|
|
||||||
use deno_media_type::MediaType;
|
use deno_media_type::MediaType;
|
||||||
use deno_resolver::cjs::CjsTracker;
|
use deno_resolver::loader::LoadedModuleSource;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_runtime::deno_core::FastString;
|
||||||
use deno_runtime::deno_core::ModuleSourceCode;
|
use deno_runtime::deno_core::ModuleSourceCode;
|
||||||
use deno_runtime::deno_core::ModuleType;
|
use deno_runtime::deno_core::ModuleType;
|
||||||
use node_resolver::InNpmPackageChecker;
|
use deno_runtime::deno_core::RequestedModuleType;
|
||||||
use node_resolver::IsBuiltInNodeModuleChecker;
|
|
||||||
use node_resolver::NpmPackageFolderResolver;
|
|
||||||
use node_resolver::analyze::CjsCodeAnalyzer;
|
|
||||||
use node_resolver::analyze::NodeCodeTranslator;
|
|
||||||
use thiserror::Error;
|
|
||||||
use url::Url;
|
|
||||||
|
|
||||||
use crate::sys::DenoLibSys;
|
pub fn module_type_from_media_and_requested_type(
|
||||||
use crate::util::text_encoding::from_utf8_lossy_cow;
|
media_type: MediaType,
|
||||||
|
requested_module_type: &RequestedModuleType,
|
||||||
pub struct ModuleCodeStringSource {
|
) -> ModuleType {
|
||||||
pub code: ModuleSourceCode,
|
match requested_module_type {
|
||||||
pub found_url: Url,
|
RequestedModuleType::Json => ModuleType::Json,
|
||||||
pub module_type: ModuleType,
|
RequestedModuleType::Text => ModuleType::Text,
|
||||||
}
|
RequestedModuleType::Bytes => ModuleType::Bytes,
|
||||||
|
RequestedModuleType::None | RequestedModuleType::Other(_) => {
|
||||||
#[derive(Debug, Error, deno_error::JsError)]
|
|
||||||
#[class(type)]
|
|
||||||
#[error("[{}]: Stripping types is currently unsupported for files under node_modules, for \"{}\"", self.code(), specifier)]
|
|
||||||
pub struct StrippingTypesNodeModulesError {
|
|
||||||
pub specifier: Url,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl StrippingTypesNodeModulesError {
|
|
||||||
pub fn code(&self) -> &'static str {
|
|
||||||
"ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Error, deno_error::JsError)]
|
|
||||||
pub enum NpmModuleLoadError {
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
StrippingTypesNodeModules(#[from] StrippingTypesNodeModulesError),
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
ClosestPkgJson(#[from] node_resolver::errors::ClosestPkgJsonError),
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(transparent)]
|
|
||||||
TranslateCjsToEsm(#[from] node_resolver::analyze::TranslateCjsToEsmError),
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error("Unable to load {}{}", file_path.display(), maybe_referrer.as_ref().map(|r| format!(" imported from {}", r)).unwrap_or_default())]
|
|
||||||
UnableToLoad {
|
|
||||||
file_path: PathBuf,
|
|
||||||
maybe_referrer: Option<Url>,
|
|
||||||
#[source]
|
|
||||||
#[inherit]
|
|
||||||
source: std::io::Error,
|
|
||||||
},
|
|
||||||
#[class(inherit)]
|
|
||||||
#[error(
|
|
||||||
"{}",
|
|
||||||
format_dir_import_message(file_path, maybe_referrer, suggestion)
|
|
||||||
)]
|
|
||||||
DirImport {
|
|
||||||
file_path: PathBuf,
|
|
||||||
maybe_referrer: Option<Url>,
|
|
||||||
suggestion: Option<&'static str>,
|
|
||||||
#[source]
|
|
||||||
#[inherit]
|
|
||||||
source: std::io::Error,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
fn format_dir_import_message(
|
|
||||||
file_path: &std::path::Path,
|
|
||||||
maybe_referrer: &Option<Url>,
|
|
||||||
suggestion: &Option<&'static str>,
|
|
||||||
) -> String {
|
|
||||||
// directory imports are not allowed when importing from an
|
|
||||||
// ES module, so provide the user with a helpful error message
|
|
||||||
let dir_path = file_path;
|
|
||||||
let mut msg = "Directory import ".to_string();
|
|
||||||
msg.push_str(&dir_path.to_string_lossy());
|
|
||||||
if let Some(referrer) = maybe_referrer {
|
|
||||||
msg.push_str(" is not supported resolving import from ");
|
|
||||||
msg.push_str(referrer.as_str());
|
|
||||||
if let Some(entrypoint_name) = suggestion {
|
|
||||||
msg.push_str("\nDid you mean to import ");
|
|
||||||
msg.push_str(entrypoint_name);
|
|
||||||
msg.push_str(" within the directory?");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
msg
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct NpmModuleLoader<
|
|
||||||
TCjsCodeAnalyzer: CjsCodeAnalyzer,
|
|
||||||
TInNpmPackageChecker: InNpmPackageChecker,
|
|
||||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
|
||||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
|
||||||
TSys: DenoLibSys,
|
|
||||||
> {
|
|
||||||
cjs_tracker: Arc<CjsTracker<DenoInNpmPackageChecker, TSys>>,
|
|
||||||
sys: TSys,
|
|
||||||
node_code_translator: Arc<
|
|
||||||
NodeCodeTranslator<
|
|
||||||
TCjsCodeAnalyzer,
|
|
||||||
TInNpmPackageChecker,
|
|
||||||
TIsBuiltInNodeModuleChecker,
|
|
||||||
TNpmPackageFolderResolver,
|
|
||||||
TSys,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<
|
|
||||||
TCjsCodeAnalyzer: CjsCodeAnalyzer,
|
|
||||||
TInNpmPackageChecker: InNpmPackageChecker,
|
|
||||||
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
|
||||||
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
|
||||||
TSys: DenoLibSys,
|
|
||||||
>
|
|
||||||
NpmModuleLoader<
|
|
||||||
TCjsCodeAnalyzer,
|
|
||||||
TInNpmPackageChecker,
|
|
||||||
TIsBuiltInNodeModuleChecker,
|
|
||||||
TNpmPackageFolderResolver,
|
|
||||||
TSys,
|
|
||||||
>
|
|
||||||
{
|
|
||||||
pub fn new(
|
|
||||||
cjs_tracker: Arc<CjsTracker<DenoInNpmPackageChecker, TSys>>,
|
|
||||||
node_code_translator: Arc<
|
|
||||||
NodeCodeTranslator<
|
|
||||||
TCjsCodeAnalyzer,
|
|
||||||
TInNpmPackageChecker,
|
|
||||||
TIsBuiltInNodeModuleChecker,
|
|
||||||
TNpmPackageFolderResolver,
|
|
||||||
TSys,
|
|
||||||
>,
|
|
||||||
>,
|
|
||||||
sys: TSys,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
cjs_tracker,
|
|
||||||
node_code_translator,
|
|
||||||
sys,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn load(
|
|
||||||
&self,
|
|
||||||
specifier: &Url,
|
|
||||||
maybe_referrer: Option<&Url>,
|
|
||||||
) -> Result<ModuleCodeStringSource, NpmModuleLoadError> {
|
|
||||||
let file_path = deno_path_util::url_to_file_path(specifier)?;
|
|
||||||
let code = self.sys.fs_read(&file_path).map_err(|source| {
|
|
||||||
if self.sys.fs_is_dir_no_err(&file_path) {
|
|
||||||
let suggestion = ["index.mjs", "index.js", "index.cjs"]
|
|
||||||
.into_iter()
|
|
||||||
.find(|e| self.sys.fs_is_file_no_err(file_path.join(e)));
|
|
||||||
NpmModuleLoadError::DirImport {
|
|
||||||
file_path,
|
|
||||||
maybe_referrer: maybe_referrer.cloned(),
|
|
||||||
suggestion,
|
|
||||||
source,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
NpmModuleLoadError::UnableToLoad {
|
|
||||||
file_path,
|
|
||||||
maybe_referrer: maybe_referrer.cloned(),
|
|
||||||
source,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let media_type = MediaType::from_specifier(specifier);
|
|
||||||
if media_type.is_emittable() {
|
|
||||||
return Err(NpmModuleLoadError::StrippingTypesNodeModules(
|
|
||||||
StrippingTypesNodeModulesError {
|
|
||||||
specifier: specifier.clone(),
|
|
||||||
},
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
let code = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
|
|
||||||
// translate cjs to esm if it's cjs and inject node globals
|
|
||||||
let code = from_utf8_lossy_cow(code);
|
|
||||||
ModuleSourceCode::String(
|
|
||||||
self
|
|
||||||
.node_code_translator
|
|
||||||
.translate_cjs_to_esm(specifier, Some(code))
|
|
||||||
.await?
|
|
||||||
.into_owned()
|
|
||||||
.into(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
// esm and json code is untouched
|
|
||||||
ModuleSourceCode::Bytes(match code {
|
|
||||||
Cow::Owned(bytes) => bytes.into_boxed_slice().into(),
|
|
||||||
Cow::Borrowed(bytes) => bytes.into(),
|
|
||||||
})
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(ModuleCodeStringSource {
|
|
||||||
code,
|
|
||||||
found_url: specifier.clone(),
|
|
||||||
module_type: module_type_from_media_type(MediaType::from_specifier(
|
|
||||||
specifier,
|
|
||||||
)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn module_type_from_media_type(media_type: MediaType) -> ModuleType {
|
|
||||||
match media_type {
|
match media_type {
|
||||||
MediaType::Json => ModuleType::Json,
|
MediaType::Json => ModuleType::Json,
|
||||||
MediaType::Wasm => ModuleType::Wasm,
|
MediaType::Wasm => ModuleType::Wasm,
|
||||||
_ => ModuleType::JavaScript,
|
_ => ModuleType::JavaScript,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn loaded_module_source_to_module_source_code(
|
||||||
|
loaded_module_source: LoadedModuleSource,
|
||||||
|
) -> ModuleSourceCode {
|
||||||
|
match loaded_module_source {
|
||||||
|
LoadedModuleSource::ArcStr(text) => ModuleSourceCode::String(text.into()),
|
||||||
|
LoadedModuleSource::ArcBytes(bytes) => {
|
||||||
|
ModuleSourceCode::Bytes(bytes.into())
|
||||||
|
}
|
||||||
|
LoadedModuleSource::String(text) => match text {
|
||||||
|
Cow::Borrowed(static_text) => {
|
||||||
|
ModuleSourceCode::String(FastString::from_static(static_text))
|
||||||
|
}
|
||||||
|
Cow::Owned(text) => ModuleSourceCode::String(text.into()),
|
||||||
|
},
|
||||||
|
LoadedModuleSource::Bytes(bytes) => match bytes {
|
||||||
|
Cow::Borrowed(static_bytes) => {
|
||||||
|
ModuleSourceCode::Bytes(static_bytes.into())
|
||||||
|
}
|
||||||
|
Cow::Owned(bytes) => {
|
||||||
|
ModuleSourceCode::Bytes(bytes.into_boxed_slice().into())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn as_deno_resolver_requested_module_type(
|
||||||
|
value: &RequestedModuleType,
|
||||||
|
) -> deno_resolver::loader::RequestedModuleType<'_> {
|
||||||
|
match value {
|
||||||
|
RequestedModuleType::None => {
|
||||||
|
deno_resolver::loader::RequestedModuleType::None
|
||||||
|
}
|
||||||
|
RequestedModuleType::Json => {
|
||||||
|
deno_resolver::loader::RequestedModuleType::Json
|
||||||
|
}
|
||||||
|
RequestedModuleType::Text => {
|
||||||
|
deno_resolver::loader::RequestedModuleType::Text
|
||||||
|
}
|
||||||
|
RequestedModuleType::Bytes => {
|
||||||
|
deno_resolver::loader::RequestedModuleType::Bytes
|
||||||
|
}
|
||||||
|
RequestedModuleType::Other(text) => {
|
||||||
|
deno_resolver::loader::RequestedModuleType::Other(text)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ pub fn is_valid_utf8(bytes: &[u8]) -> bool {
|
||||||
matches!(String::from_utf8_lossy(bytes), Cow::Borrowed(_))
|
matches!(String::from_utf8_lossy(bytes), Cow::Borrowed(_))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// todo(https://github.com/rust-lang/rust/issues/129436): remove once stabilized
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
pub fn from_utf8_lossy_owned(bytes: Vec<u8>) -> String {
|
pub fn from_utf8_lossy_owned(bytes: Vec<u8>) -> String {
|
||||||
match String::from_utf8_lossy(&bytes) {
|
match String::from_utf8_lossy(&bytes) {
|
||||||
|
|
|
@ -43,10 +43,9 @@ use deno_error::JsErrorBox;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
use deno_graph::ModuleGraph;
|
use deno_graph::ModuleGraph;
|
||||||
use deno_graph::WalkOptions;
|
use deno_graph::WalkOptions;
|
||||||
use deno_lib::loader::ModuleCodeStringSource;
|
use deno_lib::loader::as_deno_resolver_requested_module_type;
|
||||||
use deno_lib::loader::NpmModuleLoadError;
|
use deno_lib::loader::loaded_module_source_to_module_source_code;
|
||||||
use deno_lib::loader::StrippingTypesNodeModulesError;
|
use deno_lib::loader::module_type_from_media_and_requested_type;
|
||||||
use deno_lib::loader::module_type_from_media_type;
|
|
||||||
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
||||||
use deno_lib::util::hash::FastInsecureHasher;
|
use deno_lib::util::hash::FastInsecureHasher;
|
||||||
use deno_lib::worker::CreateModuleLoaderResult;
|
use deno_lib::worker::CreateModuleLoaderResult;
|
||||||
|
@ -57,8 +56,10 @@ use deno_resolver::file_fetcher::FetchPermissionsOptionRef;
|
||||||
use deno_resolver::graph::ResolveWithGraphErrorKind;
|
use deno_resolver::graph::ResolveWithGraphErrorKind;
|
||||||
use deno_resolver::graph::ResolveWithGraphOptions;
|
use deno_resolver::graph::ResolveWithGraphOptions;
|
||||||
use deno_resolver::loader::LoadPreparedModuleError;
|
use deno_resolver::loader::LoadPreparedModuleError;
|
||||||
use deno_resolver::loader::PreparedModuleOrAsset;
|
use deno_resolver::loader::LoadedModule;
|
||||||
use deno_resolver::loader::PreparedModuleSource;
|
use deno_resolver::loader::LoadedModuleOrAsset;
|
||||||
|
use deno_resolver::loader::NpmModuleLoadError;
|
||||||
|
use deno_resolver::loader::StrippingTypesNodeModulesError;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_resolver::npm::ResolveNpmReqRefError;
|
use deno_resolver::npm::ResolveNpmReqRefError;
|
||||||
use deno_runtime::code_cache;
|
use deno_runtime::code_cache;
|
||||||
|
@ -69,7 +70,6 @@ use deno_runtime::deno_permissions::CheckSpecifierKind;
|
||||||
use deno_runtime::deno_permissions::PermissionsContainer;
|
use deno_runtime::deno_permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use eszip::EszipV2;
|
use eszip::EszipV2;
|
||||||
use node_resolver::DenoIsBuiltInNodeModuleChecker;
|
|
||||||
use node_resolver::InNpmPackageChecker;
|
use node_resolver::InNpmPackageChecker;
|
||||||
use node_resolver::NodeResolutionKind;
|
use node_resolver::NodeResolutionKind;
|
||||||
use node_resolver::ResolutionMode;
|
use node_resolver::ResolutionMode;
|
||||||
|
@ -92,7 +92,6 @@ use crate::graph_container::ModuleGraphUpdatePermit;
|
||||||
use crate::graph_util::BuildGraphRequest;
|
use crate::graph_util::BuildGraphRequest;
|
||||||
use crate::graph_util::BuildGraphWithNpmOptions;
|
use crate::graph_util::BuildGraphWithNpmOptions;
|
||||||
use crate::graph_util::ModuleGraphBuilder;
|
use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::node::CliCjsCodeAnalyzer;
|
|
||||||
use crate::npm::CliNpmResolver;
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CliCjsTracker;
|
use crate::resolver::CliCjsTracker;
|
||||||
use crate::resolver::CliResolver;
|
use crate::resolver::CliResolver;
|
||||||
|
@ -104,13 +103,8 @@ use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::text_encoding::code_without_source_map;
|
use crate::util::text_encoding::code_without_source_map;
|
||||||
use crate::util::text_encoding::source_map_from_code;
|
use crate::util::text_encoding::source_map_from_code;
|
||||||
|
|
||||||
pub type CliNpmModuleLoader = deno_lib::loader::NpmModuleLoader<
|
pub type CliNpmModuleLoader =
|
||||||
CliCjsCodeAnalyzer,
|
deno_resolver::loader::DenoNpmModuleLoader<CliSys>;
|
||||||
DenoInNpmPackageChecker,
|
|
||||||
DenoIsBuiltInNodeModuleChecker,
|
|
||||||
CliNpmResolver,
|
|
||||||
CliSys,
|
|
||||||
>;
|
|
||||||
pub type CliEmitter =
|
pub type CliEmitter =
|
||||||
deno_resolver::emit::Emitter<DenoInNpmPackageChecker, CliSys>;
|
deno_resolver::emit::Emitter<DenoInNpmPackageChecker, CliSys>;
|
||||||
pub type CliPreparedModuleLoader =
|
pub type CliPreparedModuleLoader =
|
||||||
|
@ -336,7 +330,7 @@ struct SharedCliModuleLoaderState {
|
||||||
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
npm_module_loader: CliNpmModuleLoader,
|
npm_module_loader: Arc<CliNpmModuleLoader>,
|
||||||
npm_registry_permission_checker:
|
npm_registry_permission_checker:
|
||||||
Arc<NpmRegistryReadPermissionChecker<CliSys>>,
|
Arc<NpmRegistryReadPermissionChecker<CliSys>>,
|
||||||
npm_resolver: CliNpmResolver,
|
npm_resolver: CliNpmResolver,
|
||||||
|
@ -398,7 +392,7 @@ impl CliModuleLoaderFactory {
|
||||||
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
in_npm_pkg_checker: DenoInNpmPackageChecker,
|
||||||
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
main_module_graph_container: Arc<MainModuleGraphContainer>,
|
||||||
module_load_preparer: Arc<ModuleLoadPreparer>,
|
module_load_preparer: Arc<ModuleLoadPreparer>,
|
||||||
npm_module_loader: CliNpmModuleLoader,
|
npm_module_loader: Arc<CliNpmModuleLoader>,
|
||||||
npm_registry_permission_checker: Arc<
|
npm_registry_permission_checker: Arc<
|
||||||
NpmRegistryReadPermissionChecker<CliSys>,
|
NpmRegistryReadPermissionChecker<CliSys>,
|
||||||
>,
|
>,
|
||||||
|
@ -530,6 +524,12 @@ impl CliModuleLoaderFactory {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ModuleCodeStringSource {
|
||||||
|
pub code: ModuleSourceCode,
|
||||||
|
pub found_url: ModuleSpecifier,
|
||||||
|
pub module_type: ModuleType,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
#[class(generic)]
|
#[class(generic)]
|
||||||
#[error("Loading unprepared module: {}{}", .specifier, .maybe_referrer.as_ref().map(|r| format!(", imported from: {}", r)).unwrap_or_default())]
|
#[error("Loading unprepared module: {}{}", .specifier, .maybe_referrer.as_ref().map(|r| format!(", imported from: {}", r)).unwrap_or_default())]
|
||||||
|
@ -712,63 +712,28 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
maybe_referrer: Option<&ModuleSpecifier>,
|
maybe_referrer: Option<&ModuleSpecifier>,
|
||||||
requested_module_type: &RequestedModuleType,
|
requested_module_type: &RequestedModuleType,
|
||||||
) -> Result<ModuleCodeStringSource, LoadCodeSourceError> {
|
) -> Result<ModuleCodeStringSource, LoadCodeSourceError> {
|
||||||
fn as_deno_resolver_requested_module_type(
|
|
||||||
value: &RequestedModuleType,
|
|
||||||
) -> deno_resolver::loader::RequestedModuleType<'_> {
|
|
||||||
match value {
|
|
||||||
RequestedModuleType::None => {
|
|
||||||
deno_resolver::loader::RequestedModuleType::None
|
|
||||||
}
|
|
||||||
RequestedModuleType::Json => {
|
|
||||||
deno_resolver::loader::RequestedModuleType::Json
|
|
||||||
}
|
|
||||||
RequestedModuleType::Text => {
|
|
||||||
deno_resolver::loader::RequestedModuleType::Text
|
|
||||||
}
|
|
||||||
RequestedModuleType::Bytes => {
|
|
||||||
deno_resolver::loader::RequestedModuleType::Bytes
|
|
||||||
}
|
|
||||||
RequestedModuleType::Other(text) => {
|
|
||||||
deno_resolver::loader::RequestedModuleType::Other(text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let graph = self.graph_container.graph();
|
let graph = self.graph_container.graph();
|
||||||
|
let deno_resolver_requested_module_type =
|
||||||
|
as_deno_resolver_requested_module_type(requested_module_type);
|
||||||
match self
|
match self
|
||||||
.shared
|
.shared
|
||||||
.prepared_module_loader
|
.prepared_module_loader
|
||||||
.load_prepared_module(
|
.load_prepared_module(
|
||||||
&graph,
|
&graph,
|
||||||
specifier,
|
specifier,
|
||||||
&as_deno_resolver_requested_module_type(requested_module_type),
|
&deno_resolver_requested_module_type,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(LoadCodeSourceError::from)?
|
.map_err(LoadCodeSourceError::from)?
|
||||||
{
|
{
|
||||||
Some(module_or_asset) => match module_or_asset {
|
Some(module_or_asset) => match module_or_asset {
|
||||||
PreparedModuleOrAsset::Module(prepared_module) => {
|
LoadedModuleOrAsset::Module(prepared_module) => {
|
||||||
Ok(ModuleCodeStringSource {
|
Ok(self.loaded_module_to_module_code_string_source(
|
||||||
code: match prepared_module.source {
|
prepared_module,
|
||||||
PreparedModuleSource::ArcStr(text) => {
|
requested_module_type,
|
||||||
ModuleSourceCode::String(text.into())
|
))
|
||||||
}
|
}
|
||||||
PreparedModuleSource::ArcBytes(bytes) => {
|
LoadedModuleOrAsset::ExternalAsset { specifier } => {
|
||||||
ModuleSourceCode::Bytes(bytes.into())
|
|
||||||
}
|
|
||||||
},
|
|
||||||
found_url: prepared_module.specifier.clone(),
|
|
||||||
module_type: match requested_module_type {
|
|
||||||
RequestedModuleType::Json => ModuleType::Json,
|
|
||||||
RequestedModuleType::Text => ModuleType::Text,
|
|
||||||
RequestedModuleType::Bytes => ModuleType::Bytes,
|
|
||||||
RequestedModuleType::None | RequestedModuleType::Other(_) => {
|
|
||||||
module_type_from_media_type(prepared_module.media_type)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
})
|
|
||||||
}
|
|
||||||
PreparedModuleOrAsset::ExternalAsset { specifier } => {
|
|
||||||
self.load_asset(
|
self.load_asset(
|
||||||
specifier,
|
specifier,
|
||||||
/* do not use dynamic import permissions because this was statically analyzable */ CheckSpecifierKind::Static,
|
/* do not use dynamic import permissions because this was statically analyzable */ CheckSpecifierKind::Static,
|
||||||
|
@ -812,13 +777,22 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
} else {
|
} else {
|
||||||
Cow::Borrowed(specifier)
|
Cow::Borrowed(specifier)
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.shared.in_npm_pkg_checker.in_npm_package(&specifier) {
|
if self.shared.in_npm_pkg_checker.in_npm_package(&specifier) {
|
||||||
return self
|
let loaded_module = self
|
||||||
.shared
|
.shared
|
||||||
.npm_module_loader
|
.npm_module_loader
|
||||||
.load(&specifier, maybe_referrer)
|
.load(
|
||||||
|
&specifier,
|
||||||
|
maybe_referrer,
|
||||||
|
&deno_resolver_requested_module_type,
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(LoadCodeSourceError::from);
|
.map_err(LoadCodeSourceError::from)?;
|
||||||
|
return Ok(self.loaded_module_to_module_code_string_source(
|
||||||
|
loaded_module,
|
||||||
|
requested_module_type,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
match requested_module_type {
|
match requested_module_type {
|
||||||
|
@ -839,6 +813,21 @@ impl<TGraphContainer: ModuleGraphContainer>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn loaded_module_to_module_code_string_source(
|
||||||
|
&self,
|
||||||
|
loaded_module: LoadedModule,
|
||||||
|
requested_module_type: &RequestedModuleType,
|
||||||
|
) -> ModuleCodeStringSource {
|
||||||
|
ModuleCodeStringSource {
|
||||||
|
code: loaded_module_source_to_module_source_code(loaded_module.source),
|
||||||
|
found_url: loaded_module.specifier.clone(),
|
||||||
|
module_type: module_type_from_media_and_requested_type(
|
||||||
|
loaded_module.media_type,
|
||||||
|
requested_module_type,
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async fn load_asset(
|
async fn load_asset(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
|
|
|
@ -5,9 +5,9 @@ use std::sync::Arc;
|
||||||
|
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_error::JsErrorBox;
|
use deno_error::JsErrorBox;
|
||||||
use deno_lib::loader::NpmModuleLoader;
|
|
||||||
use deno_lib::standalone::binary::CjsExportAnalysisEntry;
|
use deno_lib::standalone::binary::CjsExportAnalysisEntry;
|
||||||
use deno_media_type::MediaType;
|
use deno_media_type::MediaType;
|
||||||
|
use deno_resolver::loader::NpmModuleLoader;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
use deno_resolver::npm::NpmReqResolver;
|
use deno_resolver::npm::NpmReqResolver;
|
||||||
use deno_runtime::deno_fs::FileSystem;
|
use deno_runtime::deno_fs::FileSystem;
|
||||||
|
|
|
@ -27,7 +27,9 @@ use deno_lib::args::CaData;
|
||||||
use deno_lib::args::RootCertStoreLoadError;
|
use deno_lib::args::RootCertStoreLoadError;
|
||||||
use deno_lib::args::get_root_cert_store;
|
use deno_lib::args::get_root_cert_store;
|
||||||
use deno_lib::args::npm_pkg_req_ref_to_binary_command;
|
use deno_lib::args::npm_pkg_req_ref_to_binary_command;
|
||||||
use deno_lib::loader::NpmModuleLoader;
|
use deno_lib::loader::as_deno_resolver_requested_module_type;
|
||||||
|
use deno_lib::loader::loaded_module_source_to_module_source_code;
|
||||||
|
use deno_lib::loader::module_type_from_media_and_requested_type;
|
||||||
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
use deno_lib::npm::NpmRegistryReadPermissionChecker;
|
||||||
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
|
use deno_lib::npm::NpmRegistryReadPermissionCheckerMode;
|
||||||
use deno_lib::npm::create_npm_process_state_provider;
|
use deno_lib::npm::create_npm_process_state_provider;
|
||||||
|
@ -48,6 +50,7 @@ use deno_package_json::PackageJsonDepValue;
|
||||||
use deno_resolver::DenoResolveErrorKind;
|
use deno_resolver::DenoResolveErrorKind;
|
||||||
use deno_resolver::cjs::CjsTracker;
|
use deno_resolver::cjs::CjsTracker;
|
||||||
use deno_resolver::cjs::IsCjsResolutionMode;
|
use deno_resolver::cjs::IsCjsResolutionMode;
|
||||||
|
use deno_resolver::loader::NpmModuleLoader;
|
||||||
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
|
use deno_resolver::npm::ByonmNpmResolverCreateOptions;
|
||||||
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
use deno_resolver::npm::CreateInNpmPkgCheckerOptions;
|
||||||
use deno_resolver::npm::DenoInNpmPackageChecker;
|
use deno_resolver::npm::DenoInNpmPackageChecker;
|
||||||
|
@ -404,18 +407,31 @@ impl ModuleLoader for EmbeddedModuleLoader {
|
||||||
async move {
|
async move {
|
||||||
let code_source = shared
|
let code_source = shared
|
||||||
.npm_module_loader
|
.npm_module_loader
|
||||||
.load(&original_specifier, maybe_referrer.as_ref())
|
.load(
|
||||||
|
&original_specifier,
|
||||||
|
maybe_referrer.as_ref(),
|
||||||
|
&as_deno_resolver_requested_module_type(&requested_module_type),
|
||||||
|
)
|
||||||
.await
|
.await
|
||||||
.map_err(JsErrorBox::from_err)?;
|
.map_err(JsErrorBox::from_err)?;
|
||||||
let code_cache_entry = shared.get_code_cache(
|
let code_cache_entry = match requested_module_type {
|
||||||
&code_source.found_url,
|
RequestedModuleType::None => shared.get_code_cache(
|
||||||
code_source.code.as_bytes(),
|
code_source.specifier,
|
||||||
);
|
code_source.source.as_bytes(),
|
||||||
|
),
|
||||||
|
RequestedModuleType::Other(_)
|
||||||
|
| RequestedModuleType::Json
|
||||||
|
| RequestedModuleType::Text
|
||||||
|
| RequestedModuleType::Bytes => None,
|
||||||
|
};
|
||||||
Ok(deno_core::ModuleSource::new_with_redirect(
|
Ok(deno_core::ModuleSource::new_with_redirect(
|
||||||
code_source.module_type,
|
module_type_from_media_and_requested_type(
|
||||||
code_source.code,
|
code_source.media_type,
|
||||||
|
&requested_module_type,
|
||||||
|
),
|
||||||
|
loaded_module_source_to_module_source_code(code_source.source),
|
||||||
&original_specifier,
|
&original_specifier,
|
||||||
&code_source.found_url,
|
code_source.specifier,
|
||||||
code_cache_entry,
|
code_cache_entry,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
|
@ -200,7 +200,7 @@ pub enum PackageJsonLoadError {
|
||||||
source: serde_json::Error,
|
source: serde_json::Error,
|
||||||
},
|
},
|
||||||
#[error(
|
#[error(
|
||||||
"\"exports\" cannot contains some keys starting with '.' and some not.\nThe exports object must either be an object of package subpath keys\nor an object of main entry condition name keys only."
|
"\"exports\" cannot contain some keys starting with '.' and some not.\nThe exports object must either be an object of package subpath keys\nor an object of main entry condition name keys only."
|
||||||
)]
|
)]
|
||||||
#[class(type)]
|
#[class(type)]
|
||||||
InvalidExports,
|
InvalidExports,
|
||||||
|
|
|
@ -61,6 +61,8 @@ use crate::deno_json::CompilerOptionsResolver;
|
||||||
use crate::deno_json::CompilerOptionsResolverRc;
|
use crate::deno_json::CompilerOptionsResolverRc;
|
||||||
use crate::import_map::WorkspaceExternalImportMapLoader;
|
use crate::import_map::WorkspaceExternalImportMapLoader;
|
||||||
use crate::import_map::WorkspaceExternalImportMapLoaderRc;
|
use crate::import_map::WorkspaceExternalImportMapLoaderRc;
|
||||||
|
use crate::loader::DenoNpmModuleLoaderRc;
|
||||||
|
use crate::loader::NpmModuleLoader;
|
||||||
use crate::lockfile::LockfileLock;
|
use crate::lockfile::LockfileLock;
|
||||||
use crate::lockfile::LockfileLockRc;
|
use crate::lockfile::LockfileLockRc;
|
||||||
use crate::npm::ByonmNpmResolverCreateOptions;
|
use crate::npm::ByonmNpmResolverCreateOptions;
|
||||||
|
@ -224,6 +226,7 @@ pub trait WorkspaceFactorySys:
|
||||||
+ crate::npm::NpmResolverSys
|
+ crate::npm::NpmResolverSys
|
||||||
+ deno_cache_dir::GlobalHttpCacheSys
|
+ deno_cache_dir::GlobalHttpCacheSys
|
||||||
+ deno_cache_dir::LocalHttpCacheSys
|
+ deno_cache_dir::LocalHttpCacheSys
|
||||||
|
+ crate::loader::NpmModuleLoaderSys
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,6 +696,7 @@ pub struct ResolverFactory<TSys: WorkspaceFactorySys> {
|
||||||
found_package_json_dep_flag: crate::graph::FoundPackageJsonDepFlagRc,
|
found_package_json_dep_flag: crate::graph::FoundPackageJsonDepFlagRc,
|
||||||
in_npm_package_checker: Deferred<DenoInNpmPackageChecker>,
|
in_npm_package_checker: Deferred<DenoInNpmPackageChecker>,
|
||||||
node_code_translator: Deferred<DenoNodeCodeTranslatorRc<TSys>>,
|
node_code_translator: Deferred<DenoNodeCodeTranslatorRc<TSys>>,
|
||||||
|
npm_module_loader: Deferred<DenoNpmModuleLoaderRc<TSys>>,
|
||||||
node_resolver: Deferred<
|
node_resolver: Deferred<
|
||||||
NodeResolverRc<
|
NodeResolverRc<
|
||||||
DenoInNpmPackageChecker,
|
DenoInNpmPackageChecker,
|
||||||
|
@ -746,6 +750,7 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
in_npm_package_checker: Default::default(),
|
in_npm_package_checker: Default::default(),
|
||||||
node_code_translator: Default::default(),
|
node_code_translator: Default::default(),
|
||||||
node_resolver: Default::default(),
|
node_resolver: Default::default(),
|
||||||
|
npm_module_loader: Default::default(),
|
||||||
npm_req_resolver: Default::default(),
|
npm_req_resolver: Default::default(),
|
||||||
npm_resolution: Default::default(),
|
npm_resolution: Default::default(),
|
||||||
npm_resolver: Default::default(),
|
npm_resolver: Default::default(),
|
||||||
|
@ -949,6 +954,18 @@ impl<TSys: WorkspaceFactorySys> ResolverFactory<TSys> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn npm_module_loader(
|
||||||
|
&self,
|
||||||
|
) -> Result<&DenoNpmModuleLoaderRc<TSys>, anyhow::Error> {
|
||||||
|
self.npm_module_loader.get_or_try_init(|| {
|
||||||
|
Ok(new_rc(NpmModuleLoader::new(
|
||||||
|
self.cjs_tracker()?.clone(),
|
||||||
|
self.node_code_translator()?.clone(),
|
||||||
|
self.workspace_factory.sys.clone(),
|
||||||
|
)))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
pub fn npm_resolution(&self) -> &NpmResolutionCellRc {
|
pub fn npm_resolution(&self) -> &NpmResolutionCellRc {
|
||||||
&self.npm_resolution
|
&self.npm_resolution
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
// Copyright 2018-2025 the Deno authors. MIT license.
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
mod npm;
|
||||||
|
|
||||||
|
#[cfg(all(feature = "graph", feature = "deno_ast"))]
|
||||||
|
mod prepared;
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use deno_media_type::MediaType;
|
||||||
|
pub use npm::*;
|
||||||
|
#[cfg(all(feature = "graph", feature = "deno_ast"))]
|
||||||
|
pub use prepared::*;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub enum RequestedModuleType<'a> {
|
pub enum RequestedModuleType<'a> {
|
||||||
None,
|
None,
|
||||||
Json,
|
Json,
|
||||||
|
@ -8,8 +21,31 @@ pub enum RequestedModuleType<'a> {
|
||||||
Other(&'a str),
|
Other(&'a str),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(all(feature = "graph", feature = "deno_ast"))]
|
#[allow(clippy::disallowed_types)]
|
||||||
mod prepared;
|
type ArcStr = std::sync::Arc<str>;
|
||||||
|
#[allow(clippy::disallowed_types)]
|
||||||
|
type ArcBytes = std::sync::Arc<[u8]>;
|
||||||
|
|
||||||
#[cfg(all(feature = "graph", feature = "deno_ast"))]
|
pub struct LoadedModule<'a> {
|
||||||
pub use prepared::*;
|
pub specifier: &'a Url,
|
||||||
|
pub media_type: MediaType,
|
||||||
|
pub source: LoadedModuleSource,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum LoadedModuleSource {
|
||||||
|
ArcStr(ArcStr),
|
||||||
|
ArcBytes(ArcBytes),
|
||||||
|
String(Cow<'static, str>),
|
||||||
|
Bytes(Cow<'static, [u8]>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoadedModuleSource {
|
||||||
|
pub fn as_bytes(&self) -> &[u8] {
|
||||||
|
match self {
|
||||||
|
LoadedModuleSource::ArcStr(text) => text.as_bytes(),
|
||||||
|
LoadedModuleSource::ArcBytes(bytes) => bytes,
|
||||||
|
LoadedModuleSource::String(text) => text.as_bytes(),
|
||||||
|
LoadedModuleSource::Bytes(bytes) => bytes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
251
libs/resolver/loader/npm.rs
Normal file
251
libs/resolver/loader/npm.rs
Normal file
|
@ -0,0 +1,251 @@
|
||||||
|
// Copyright 2018-2025 the Deno authors. MIT license.
|
||||||
|
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use deno_media_type::MediaType;
|
||||||
|
use node_resolver::InNpmPackageChecker;
|
||||||
|
use node_resolver::IsBuiltInNodeModuleChecker;
|
||||||
|
use node_resolver::NpmPackageFolderResolver;
|
||||||
|
use node_resolver::analyze::CjsCodeAnalyzer;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslatorRc;
|
||||||
|
use node_resolver::analyze::NodeCodeTranslatorSys;
|
||||||
|
use thiserror::Error;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use super::LoadedModule;
|
||||||
|
use super::LoadedModuleSource;
|
||||||
|
use super::RequestedModuleType;
|
||||||
|
use crate::cjs::CjsTrackerRc;
|
||||||
|
|
||||||
|
#[derive(Debug, Error, deno_error::JsError)]
|
||||||
|
#[class(type)]
|
||||||
|
#[error("[{}]: Stripping types is currently unsupported for files under node_modules, for \"{}\"", self.code(), specifier)]
|
||||||
|
pub struct StrippingTypesNodeModulesError {
|
||||||
|
pub specifier: Url,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StrippingTypesNodeModulesError {
|
||||||
|
pub fn code(&self) -> &'static str {
|
||||||
|
"ERR_UNSUPPORTED_NODE_MODULES_TYPE_STRIPPING"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Error, deno_error::JsError)]
|
||||||
|
pub enum NpmModuleLoadError {
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
StrippingTypesNodeModules(#[from] StrippingTypesNodeModulesError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
ClosestPkgJson(#[from] node_resolver::errors::ClosestPkgJsonError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(transparent)]
|
||||||
|
TranslateCjsToEsm(#[from] node_resolver::analyze::TranslateCjsToEsmError),
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error("Unable to load {}{}", file_path.display(), maybe_referrer.as_ref().map(|r| format!(" imported from {}", r)).unwrap_or_default())]
|
||||||
|
UnableToLoad {
|
||||||
|
file_path: PathBuf,
|
||||||
|
maybe_referrer: Option<Url>,
|
||||||
|
#[source]
|
||||||
|
#[inherit]
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
|
#[class(inherit)]
|
||||||
|
#[error(
|
||||||
|
"{}",
|
||||||
|
format_dir_import_message(file_path, maybe_referrer, suggestion)
|
||||||
|
)]
|
||||||
|
DirImport {
|
||||||
|
file_path: PathBuf,
|
||||||
|
maybe_referrer: Option<Url>,
|
||||||
|
suggestion: Option<&'static str>,
|
||||||
|
#[source]
|
||||||
|
#[inherit]
|
||||||
|
source: std::io::Error,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
fn format_dir_import_message(
|
||||||
|
file_path: &std::path::Path,
|
||||||
|
maybe_referrer: &Option<Url>,
|
||||||
|
suggestion: &Option<&'static str>,
|
||||||
|
) -> String {
|
||||||
|
// directory imports are not allowed when importing from an
|
||||||
|
// ES module, so provide the user with a helpful error message
|
||||||
|
let dir_path = file_path;
|
||||||
|
let mut msg = "Directory import ".to_string();
|
||||||
|
msg.push_str(&dir_path.to_string_lossy());
|
||||||
|
if let Some(referrer) = maybe_referrer {
|
||||||
|
msg.push_str(" is not supported resolving import from ");
|
||||||
|
msg.push_str(referrer.as_str());
|
||||||
|
if let Some(entrypoint_name) = suggestion {
|
||||||
|
msg.push_str("\nDid you mean to import ");
|
||||||
|
msg.push_str(entrypoint_name);
|
||||||
|
msg.push_str(" within the directory?");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg
|
||||||
|
}
|
||||||
|
|
||||||
|
#[sys_traits::auto_impl]
|
||||||
|
pub trait NpmModuleLoaderSys: NodeCodeTranslatorSys {}
|
||||||
|
|
||||||
|
#[allow(clippy::disallowed_types)]
|
||||||
|
pub type DenoNpmModuleLoaderRc<TSys> =
|
||||||
|
crate::sync::MaybeArc<DenoNpmModuleLoader<TSys>>;
|
||||||
|
|
||||||
|
pub type DenoNpmModuleLoader<TSys> = NpmModuleLoader<
|
||||||
|
crate::cjs::analyzer::DenoCjsCodeAnalyzer<TSys>,
|
||||||
|
crate::npm::DenoInNpmPackageChecker,
|
||||||
|
node_resolver::DenoIsBuiltInNodeModuleChecker,
|
||||||
|
crate::npm::NpmResolver<TSys>,
|
||||||
|
TSys,
|
||||||
|
>;
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub struct NpmModuleLoader<
|
||||||
|
TCjsCodeAnalyzer: CjsCodeAnalyzer,
|
||||||
|
TInNpmPackageChecker: InNpmPackageChecker,
|
||||||
|
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||||
|
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||||
|
TSys: NpmModuleLoaderSys,
|
||||||
|
> {
|
||||||
|
cjs_tracker: CjsTrackerRc<TInNpmPackageChecker, TSys>,
|
||||||
|
sys: TSys,
|
||||||
|
node_code_translator: NodeCodeTranslatorRc<
|
||||||
|
TCjsCodeAnalyzer,
|
||||||
|
TInNpmPackageChecker,
|
||||||
|
TIsBuiltInNodeModuleChecker,
|
||||||
|
TNpmPackageFolderResolver,
|
||||||
|
TSys,
|
||||||
|
>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<
|
||||||
|
TCjsCodeAnalyzer: CjsCodeAnalyzer,
|
||||||
|
TInNpmPackageChecker: InNpmPackageChecker,
|
||||||
|
TIsBuiltInNodeModuleChecker: IsBuiltInNodeModuleChecker,
|
||||||
|
TNpmPackageFolderResolver: NpmPackageFolderResolver,
|
||||||
|
TSys: NpmModuleLoaderSys,
|
||||||
|
>
|
||||||
|
NpmModuleLoader<
|
||||||
|
TCjsCodeAnalyzer,
|
||||||
|
TInNpmPackageChecker,
|
||||||
|
TIsBuiltInNodeModuleChecker,
|
||||||
|
TNpmPackageFolderResolver,
|
||||||
|
TSys,
|
||||||
|
>
|
||||||
|
{
|
||||||
|
pub fn new(
|
||||||
|
cjs_tracker: CjsTrackerRc<TInNpmPackageChecker, TSys>,
|
||||||
|
node_code_translator: NodeCodeTranslatorRc<
|
||||||
|
TCjsCodeAnalyzer,
|
||||||
|
TInNpmPackageChecker,
|
||||||
|
TIsBuiltInNodeModuleChecker,
|
||||||
|
TNpmPackageFolderResolver,
|
||||||
|
TSys,
|
||||||
|
>,
|
||||||
|
sys: TSys,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
cjs_tracker,
|
||||||
|
node_code_translator,
|
||||||
|
sys,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn load<'a>(
|
||||||
|
&self,
|
||||||
|
specifier: &'a Url,
|
||||||
|
maybe_referrer: Option<&Url>,
|
||||||
|
requested_module_type: &RequestedModuleType<'_>,
|
||||||
|
) -> Result<LoadedModule<'a>, NpmModuleLoadError> {
|
||||||
|
let file_path = deno_path_util::url_to_file_path(specifier)?;
|
||||||
|
let code = self.sys.fs_read(&file_path).map_err(|source| {
|
||||||
|
if self.sys.fs_is_dir_no_err(&file_path) {
|
||||||
|
let suggestion = ["index.mjs", "index.js", "index.cjs"]
|
||||||
|
.into_iter()
|
||||||
|
.find(|e| self.sys.fs_is_file_no_err(file_path.join(e)));
|
||||||
|
NpmModuleLoadError::DirImport {
|
||||||
|
file_path,
|
||||||
|
maybe_referrer: maybe_referrer.cloned(),
|
||||||
|
suggestion,
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NpmModuleLoadError::UnableToLoad {
|
||||||
|
file_path,
|
||||||
|
maybe_referrer: maybe_referrer.cloned(),
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let media_type = MediaType::from_specifier(specifier);
|
||||||
|
match requested_module_type {
|
||||||
|
RequestedModuleType::Text | RequestedModuleType::Bytes => {
|
||||||
|
Ok(LoadedModule {
|
||||||
|
specifier,
|
||||||
|
media_type,
|
||||||
|
source: LoadedModuleSource::Bytes(code),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
RequestedModuleType::None
|
||||||
|
| RequestedModuleType::Json
|
||||||
|
| RequestedModuleType::Other(_) => {
|
||||||
|
if media_type.is_emittable() {
|
||||||
|
return Err(NpmModuleLoadError::StrippingTypesNodeModules(
|
||||||
|
StrippingTypesNodeModulesError {
|
||||||
|
specifier: specifier.clone(),
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let source = if self.cjs_tracker.is_maybe_cjs(specifier, media_type)? {
|
||||||
|
// translate cjs to esm if it's cjs and inject node globals
|
||||||
|
let code = from_utf8_lossy_cow(code);
|
||||||
|
LoadedModuleSource::String(
|
||||||
|
self
|
||||||
|
.node_code_translator
|
||||||
|
.translate_cjs_to_esm(specifier, Some(code))
|
||||||
|
.await?
|
||||||
|
.into_owned()
|
||||||
|
.into(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// esm and json code is untouched
|
||||||
|
LoadedModuleSource::Bytes(code)
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(LoadedModule {
|
||||||
|
source,
|
||||||
|
specifier,
|
||||||
|
media_type,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn from_utf8_lossy_cow(bytes: Cow<[u8]>) -> Cow<str> {
|
||||||
|
match bytes {
|
||||||
|
Cow::Borrowed(bytes) => String::from_utf8_lossy(bytes),
|
||||||
|
Cow::Owned(bytes) => Cow::Owned(from_utf8_lossy_owned(bytes)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// todo(https://github.com/rust-lang/rust/issues/129436): remove once stabilized
|
||||||
|
#[inline(always)]
|
||||||
|
fn from_utf8_lossy_owned(bytes: Vec<u8>) -> String {
|
||||||
|
match String::from_utf8_lossy(&bytes) {
|
||||||
|
Cow::Owned(code) => code,
|
||||||
|
// SAFETY: `String::from_utf8_lossy` guarantees that the result is valid
|
||||||
|
// UTF-8 if `Cow::Borrowed` is returned.
|
||||||
|
Cow::Borrowed(_) => unsafe { String::from_utf8_unchecked(bytes) },
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@ use node_resolver::errors::ClosestPkgJsonError;
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
use super::LoadedModule;
|
||||||
|
use super::LoadedModuleSource;
|
||||||
use super::RequestedModuleType;
|
use super::RequestedModuleType;
|
||||||
use crate::cache::ParsedSourceCacheRc;
|
use crate::cache::ParsedSourceCacheRc;
|
||||||
use crate::cjs::CjsTrackerRc;
|
use crate::cjs::CjsTrackerRc;
|
||||||
|
@ -29,22 +31,6 @@ use crate::npm::NpmResolverSys;
|
||||||
|
|
||||||
#[allow(clippy::disallowed_types)]
|
#[allow(clippy::disallowed_types)]
|
||||||
type ArcStr = std::sync::Arc<str>;
|
type ArcStr = std::sync::Arc<str>;
|
||||||
#[allow(clippy::disallowed_types)]
|
|
||||||
type ArcBytes = std::sync::Arc<[u8]>;
|
|
||||||
|
|
||||||
pub enum PreparedModuleSource {
|
|
||||||
ArcStr(ArcStr),
|
|
||||||
ArcBytes(ArcBytes),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PreparedModuleSource {
|
|
||||||
pub fn as_bytes(&self) -> &[u8] {
|
|
||||||
match self {
|
|
||||||
PreparedModuleSource::ArcStr(text) => text.as_bytes(),
|
|
||||||
PreparedModuleSource::ArcBytes(bytes) => bytes,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
#[derive(Debug, thiserror::Error, deno_error::JsError)]
|
||||||
#[error("{message}")]
|
#[error("{message}")]
|
||||||
|
@ -91,14 +77,8 @@ pub trait PreparedModuleLoaderSys:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PreparedModule<'graph> {
|
pub enum LoadedModuleOrAsset<'graph> {
|
||||||
pub specifier: &'graph Url,
|
Module(LoadedModule<'graph>),
|
||||||
pub media_type: MediaType,
|
|
||||||
pub source: PreparedModuleSource,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum PreparedModuleOrAsset<'graph> {
|
|
||||||
Module(PreparedModule<'graph>),
|
|
||||||
/// A module that the graph knows about, but the data
|
/// A module that the graph knows about, but the data
|
||||||
/// is not stored in the graph itself. It's up to the caller
|
/// is not stored in the graph itself. It's up to the caller
|
||||||
/// to fetch this data.
|
/// to fetch this data.
|
||||||
|
@ -108,7 +88,7 @@ pub enum PreparedModuleOrAsset<'graph> {
|
||||||
}
|
}
|
||||||
|
|
||||||
enum CodeOrDeferredEmit<'a> {
|
enum CodeOrDeferredEmit<'a> {
|
||||||
Source(PreparedModule<'a>),
|
Source(LoadedModule<'a>),
|
||||||
DeferredEmit {
|
DeferredEmit {
|
||||||
specifier: &'a Url,
|
specifier: &'a Url,
|
||||||
media_type: MediaType,
|
media_type: MediaType,
|
||||||
|
@ -159,8 +139,7 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
graph: &'graph ModuleGraph,
|
graph: &'graph ModuleGraph,
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
requested_module_type: &RequestedModuleType<'_>,
|
requested_module_type: &RequestedModuleType<'_>,
|
||||||
) -> Result<Option<PreparedModuleOrAsset<'graph>>, LoadPreparedModuleError>
|
) -> Result<Option<LoadedModuleOrAsset<'graph>>, LoadPreparedModuleError> {
|
||||||
{
|
|
||||||
// Note: keep this in sync with the sync version below
|
// Note: keep this in sync with the sync version below
|
||||||
match self.load_prepared_module_or_defer_emit(
|
match self.load_prepared_module_or_defer_emit(
|
||||||
graph,
|
graph,
|
||||||
|
@ -168,7 +147,7 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
requested_module_type,
|
requested_module_type,
|
||||||
)? {
|
)? {
|
||||||
Some(CodeOrDeferredEmit::Source(source)) => {
|
Some(CodeOrDeferredEmit::Source(source)) => {
|
||||||
Ok(Some(PreparedModuleOrAsset::Module(source)))
|
Ok(Some(LoadedModuleOrAsset::Module(source)))
|
||||||
}
|
}
|
||||||
Some(CodeOrDeferredEmit::DeferredEmit {
|
Some(CodeOrDeferredEmit::DeferredEmit {
|
||||||
specifier,
|
specifier,
|
||||||
|
@ -183,9 +162,9 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
// at this point, we no longer need the parsed source in memory, so free it
|
// at this point, we no longer need the parsed source in memory, so free it
|
||||||
self.parsed_source_cache.free(specifier);
|
self.parsed_source_cache.free(specifier);
|
||||||
|
|
||||||
Ok(Some(PreparedModuleOrAsset::Module(PreparedModule {
|
Ok(Some(LoadedModuleOrAsset::Module(LoadedModule {
|
||||||
// note: it's faster to provide a string to v8 if we know it's a string
|
// note: it's faster to provide a string to v8 if we know it's a string
|
||||||
source: PreparedModuleSource::ArcStr(transpile_result),
|
source: LoadedModuleSource::ArcStr(transpile_result),
|
||||||
specifier,
|
specifier,
|
||||||
media_type,
|
media_type,
|
||||||
})))
|
})))
|
||||||
|
@ -198,15 +177,15 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
.load_maybe_cjs(specifier, media_type, source)
|
.load_maybe_cjs(specifier, media_type, source)
|
||||||
.await
|
.await
|
||||||
.map(|text| {
|
.map(|text| {
|
||||||
Some(PreparedModuleOrAsset::Module(PreparedModule {
|
Some(LoadedModuleOrAsset::Module(LoadedModule {
|
||||||
specifier,
|
specifier,
|
||||||
media_type,
|
media_type,
|
||||||
source: PreparedModuleSource::ArcStr(text),
|
source: LoadedModuleSource::ArcStr(text),
|
||||||
}))
|
}))
|
||||||
})
|
})
|
||||||
.map_err(LoadPreparedModuleError::LoadMaybeCjs),
|
.map_err(LoadPreparedModuleError::LoadMaybeCjs),
|
||||||
Some(CodeOrDeferredEmit::ExternalAsset { specifier }) => {
|
Some(CodeOrDeferredEmit::ExternalAsset { specifier }) => {
|
||||||
Ok(Some(PreparedModuleOrAsset::ExternalAsset { specifier }))
|
Ok(Some(LoadedModuleOrAsset::ExternalAsset { specifier }))
|
||||||
}
|
}
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
|
@ -216,7 +195,7 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
&self,
|
&self,
|
||||||
graph: &'graph ModuleGraph,
|
graph: &'graph ModuleGraph,
|
||||||
specifier: &Url,
|
specifier: &Url,
|
||||||
) -> Result<Option<PreparedModule<'graph>>, anyhow::Error> {
|
) -> Result<Option<LoadedModule<'graph>>, anyhow::Error> {
|
||||||
// Note: keep this in sync with the async version above
|
// Note: keep this in sync with the async version above
|
||||||
match self.load_prepared_module_or_defer_emit(
|
match self.load_prepared_module_or_defer_emit(
|
||||||
graph,
|
graph,
|
||||||
|
@ -239,9 +218,9 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
// at this point, we no longer need the parsed source in memory, so free it
|
// at this point, we no longer need the parsed source in memory, so free it
|
||||||
self.parsed_source_cache.free(specifier);
|
self.parsed_source_cache.free(specifier);
|
||||||
|
|
||||||
Ok(Some(PreparedModule {
|
Ok(Some(LoadedModule {
|
||||||
// note: it's faster to provide a string if we know it's a string
|
// note: it's faster to provide a string if we know it's a string
|
||||||
source: PreparedModuleSource::ArcStr(transpile_result),
|
source: LoadedModuleSource::ArcStr(transpile_result),
|
||||||
specifier,
|
specifier,
|
||||||
media_type,
|
media_type,
|
||||||
}))
|
}))
|
||||||
|
@ -282,22 +261,22 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
..
|
..
|
||||||
})) => match requested_module_type {
|
})) => match requested_module_type {
|
||||||
RequestedModuleType::Bytes => match source.try_get_original_bytes() {
|
RequestedModuleType::Bytes => match source.try_get_original_bytes() {
|
||||||
Some(bytes) => Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
Some(bytes) => Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcBytes(bytes),
|
source: LoadedModuleSource::ArcBytes(bytes),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
}))),
|
}))),
|
||||||
None => Ok(Some(CodeOrDeferredEmit::ExternalAsset { specifier })),
|
None => Ok(Some(CodeOrDeferredEmit::ExternalAsset { specifier })),
|
||||||
},
|
},
|
||||||
RequestedModuleType::Text => {
|
RequestedModuleType::Text => {
|
||||||
Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcStr(source.text.clone()),
|
source: LoadedModuleSource::ArcStr(source.text.clone()),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
})))
|
})))
|
||||||
}
|
}
|
||||||
_ => Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
_ => Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcStr(source.text.clone()),
|
source: LoadedModuleSource::ArcStr(source.text.clone()),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
}))),
|
}))),
|
||||||
|
@ -310,16 +289,16 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
..
|
..
|
||||||
})) => match requested_module_type {
|
})) => match requested_module_type {
|
||||||
RequestedModuleType::Bytes => match source.try_get_original_bytes() {
|
RequestedModuleType::Bytes => match source.try_get_original_bytes() {
|
||||||
Some(bytes) => Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
Some(bytes) => Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcBytes(bytes),
|
source: LoadedModuleSource::ArcBytes(bytes),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
}))),
|
}))),
|
||||||
None => Ok(Some(CodeOrDeferredEmit::ExternalAsset { specifier })),
|
None => Ok(Some(CodeOrDeferredEmit::ExternalAsset { specifier })),
|
||||||
},
|
},
|
||||||
RequestedModuleType::Text => {
|
RequestedModuleType::Text => {
|
||||||
Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcStr(source.text.clone()),
|
source: LoadedModuleSource::ArcStr(source.text.clone()),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
})))
|
})))
|
||||||
|
@ -373,8 +352,8 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
// at this point, we no longer need the parsed source in memory, so free it
|
// at this point, we no longer need the parsed source in memory, so free it
|
||||||
self.parsed_source_cache.free(specifier);
|
self.parsed_source_cache.free(specifier);
|
||||||
|
|
||||||
Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcStr(code),
|
source: LoadedModuleSource::ArcStr(code),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: *media_type,
|
media_type: *media_type,
|
||||||
})))
|
})))
|
||||||
|
@ -382,8 +361,8 @@ impl<TInNpmPackageChecker: InNpmPackageChecker, TSys: PreparedModuleLoaderSys>
|
||||||
},
|
},
|
||||||
Some(deno_graph::Module::Wasm(WasmModule {
|
Some(deno_graph::Module::Wasm(WasmModule {
|
||||||
source, specifier, ..
|
source, specifier, ..
|
||||||
})) => Ok(Some(CodeOrDeferredEmit::Source(PreparedModule {
|
})) => Ok(Some(CodeOrDeferredEmit::Source(LoadedModule {
|
||||||
source: PreparedModuleSource::ArcBytes(source.clone()),
|
source: LoadedModuleSource::ArcBytes(source.clone()),
|
||||||
specifier,
|
specifier,
|
||||||
media_type: MediaType::Wasm,
|
media_type: MediaType::Wasm,
|
||||||
}))),
|
}))),
|
||||||
|
|
19
tests/specs/npm/bytes_and_text_imports/__test__.jsonc
Normal file
19
tests/specs/npm/bytes_and_text_imports/__test__.jsonc
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"tempDir": true,
|
||||||
|
"tests": {
|
||||||
|
"run": {
|
||||||
|
"args": "run main.ts",
|
||||||
|
"output": "run.out"
|
||||||
|
},
|
||||||
|
"compile": {
|
||||||
|
"steps": [{
|
||||||
|
"args": "compile --unstable-raw-imports --output bin main.ts",
|
||||||
|
"output": "[WILDCARD]"
|
||||||
|
}, {
|
||||||
|
"commandName": "./bin",
|
||||||
|
"args": [],
|
||||||
|
"output": "run.out"
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
5
tests/specs/npm/bytes_and_text_imports/deno.json
Normal file
5
tests/specs/npm/bytes_and_text_imports/deno.json
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"unstable": [
|
||||||
|
"raw-imports"
|
||||||
|
]
|
||||||
|
}
|
9
tests/specs/npm/bytes_and_text_imports/main.ts
Normal file
9
tests/specs/npm/bytes_and_text_imports/main.ts
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
import bytes from "package/style.css" with { type: "bytes" };
|
||||||
|
import text from "package/style.css" with { type: "text" };
|
||||||
|
console.log(bytes);
|
||||||
|
console.log(text);
|
||||||
|
|
||||||
|
import bytesUtf8Bom from "package/style_utf8_bom.css" with { type: "bytes" };
|
||||||
|
import textUtf8Bom from "package/style_utf8_bom.css" with { type: "text" };
|
||||||
|
console.log(bytesUtf8Bom);
|
||||||
|
console.log(textUtf8Bom);
|
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/package.json
generated
vendored
Normal file
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/package.json
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
{
|
||||||
|
"name": "package"
|
||||||
|
}
|
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/style.css
generated
vendored
Normal file
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/style.css
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
div {
|
||||||
|
border-color: green;
|
||||||
|
}
|
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/style_utf8_bom.css
generated
vendored
Normal file
3
tests/specs/npm/bytes_and_text_imports/node_modules/package/style_utf8_bom.css
generated
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
div {
|
||||||
|
border-color: green;
|
||||||
|
}
|
2
tests/specs/npm/bytes_and_text_imports/package.json
Normal file
2
tests/specs/npm/bytes_and_text_imports/package.json
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
{
|
||||||
|
}
|
22
tests/specs/npm/bytes_and_text_imports/run.out
Normal file
22
tests/specs/npm/bytes_and_text_imports/run.out
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
Uint8Array(31) [
|
||||||
|
100, 105, 118, 32, 123, 10, 32,
|
||||||
|
32, 98, 111, 114, 100, 101, 114,
|
||||||
|
45, 99, 111, 108, 111, 114, 58,
|
||||||
|
32, 103, 114, 101, 101, 110, 59,
|
||||||
|
10, 125, 10
|
||||||
|
]
|
||||||
|
div {
|
||||||
|
border-color: green;
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8Array(34) [
|
||||||
|
239, 187, 191, 100, 105, 118, 32, 123,
|
||||||
|
10, 32, 32, 98, 111, 114, 100, 101,
|
||||||
|
114, 45, 99, 111, 108, 111, 114, 58,
|
||||||
|
32, 103, 114, 101, 101, 110, 59, 10,
|
||||||
|
125, 10
|
||||||
|
]
|
||||||
|
div {
|
||||||
|
border-color: green;
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue