feat(unstable): support bytes and text imports in deno compile (#29924)

Also includes:

- https://github.com/denoland/deno_graph/pull/593

Closes https://github.com/denoland/deno/issues/29903
Closes https://github.com/denoland/deno/issues/29927
This commit is contained in:
David Sherret 2025-06-28 12:24:07 -04:00 committed by GitHub
parent b5e41f605d
commit 8fcbb0fa43
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 328 additions and 24 deletions

View file

@ -14,6 +14,7 @@ use deno_core::error::AnyError;
use deno_core::serde_json;
use deno_core::url::Url;
use deno_core::FastString;
use deno_core::ModuleCodeBytes;
use deno_core::ModuleSourceCode;
use deno_core::ModuleType;
use deno_error::JsError;
@ -348,12 +349,14 @@ impl StandaloneModules {
let mut transpiled = None;
let mut source_map = None;
let mut cjs_export_analysis = None;
let mut is_valid_utf8 = false;
let bytes = match self.vfs.file_entry(&path) {
Ok(entry) => {
let bytes = self
.vfs
.read_file_all(entry)
.map_err(JsErrorBox::from_err)?;
is_valid_utf8 = entry.is_valid_utf8;
transpiled = entry
.transpiled_offset
.and_then(|t| self.vfs.read_file_offset_with_len(t).ok());
@ -379,6 +382,7 @@ impl StandaloneModules {
Ok(Some(DenoCompileModuleData {
media_type: MediaType::from_specifier(specifier),
specifier,
is_valid_utf8,
data: bytes,
transpiled,
source_map,
@ -393,6 +397,7 @@ impl StandaloneModules {
pub struct DenoCompileModuleData<'a> {
pub specifier: &'a Url,
pub media_type: MediaType,
pub is_valid_utf8: bool,
pub data: Cow<'static, [u8]>,
pub transpiled: Option<Cow<'static, [u8]>>,
pub source_map: Option<Cow<'static, [u8]>>,
@ -401,12 +406,18 @@ pub struct DenoCompileModuleData<'a> {
impl<'a> DenoCompileModuleData<'a> {
pub fn into_parts(self) -> (&'a Url, ModuleType, DenoCompileModuleSource) {
fn into_string_unsafe(data: Cow<'static, [u8]>) -> DenoCompileModuleSource {
fn into_string_unsafe(
is_valid_utf8: bool,
data: Cow<'static, [u8]>,
) -> DenoCompileModuleSource {
match data {
Cow::Borrowed(d) => DenoCompileModuleSource::String(
// SAFETY: we know this is a valid utf8 string
unsafe { std::str::from_utf8_unchecked(d) },
),
Cow::Borrowed(d) if is_valid_utf8 => {
DenoCompileModuleSource::String(
// SAFETY: we know this is a valid utf8 string
unsafe { std::str::from_utf8_unchecked(d) },
)
}
Cow::Borrowed(_) => DenoCompileModuleSource::Bytes(data),
Cow::Owned(d) => DenoCompileModuleSource::Bytes(Cow::Owned(d)),
}
}
@ -423,8 +434,14 @@ impl<'a> DenoCompileModuleData<'a> {
| MediaType::Dts
| MediaType::Dmts
| MediaType::Dcts
| MediaType::Tsx => (ModuleType::JavaScript, into_string_unsafe(data)),
MediaType::Json => (ModuleType::Json, into_string_unsafe(data)),
| MediaType::Tsx => (
ModuleType::JavaScript,
into_string_unsafe(self.is_valid_utf8, data),
),
MediaType::Json => (
ModuleType::Json,
into_string_unsafe(self.is_valid_utf8, data),
),
MediaType::Wasm => {
(ModuleType::Wasm, DenoCompileModuleSource::Bytes(data))
}
@ -441,6 +458,7 @@ impl<'a> DenoCompileModuleData<'a> {
}
}
#[derive(Debug)]
pub enum DenoCompileModuleSource {
String(&'static str),
Bytes(Cow<'static, [u8]>),
@ -448,21 +466,28 @@ pub enum DenoCompileModuleSource {
impl DenoCompileModuleSource {
pub fn into_for_v8(self) -> ModuleSourceCode {
fn into_bytes(data: Cow<'static, [u8]>) -> ModuleSourceCode {
ModuleSourceCode::Bytes(match data {
Cow::Borrowed(d) => d.into(),
Cow::Owned(d) => d.into_boxed_slice().into(),
})
}
match self {
// todo(https://github.com/denoland/deno_core/pull/943): store whether
// the string is ascii or not ahead of time so we can avoid the is_ascii()
// check in FastString::from_static
Self::String(s) => ModuleSourceCode::String(FastString::from_static(s)),
Self::Bytes(b) => into_bytes(b),
Self::Bytes(b) => ModuleSourceCode::Bytes(module_source_into_bytes(b)),
}
}
pub fn into_bytes_for_v8(self) -> ModuleCodeBytes {
match self {
DenoCompileModuleSource::String(text) => text.as_bytes().into(),
DenoCompileModuleSource::Bytes(b) => module_source_into_bytes(b),
}
}
}
fn module_source_into_bytes(data: Cow<'static, [u8]>) -> ModuleCodeBytes {
match data {
Cow::Borrowed(d) => d.into(),
Cow::Owned(d) => d.into_boxed_slice().into(),
}
}
#[derive(Debug, Error, JsError)]
@ -558,6 +583,7 @@ impl RemoteModulesStore {
self.specifiers.get_specifier(specifier).unwrap()
},
media_type: entry.media_type,
is_valid_utf8: entry.is_valid_utf8,
data: handle_cow_ref(&entry.data),
transpiled: entry.maybe_transpiled.as_ref().map(handle_cow_ref),
source_map: entry.maybe_source_map.as_ref().map(handle_cow_ref),