Repository: denoland/deno_core
Pull request #773 (2024-06-07 16:15:51)

fix: lossily UTF8 decode module source text
Towards https://github.com/denoland/deno/issues/24027


Patch:
diff --git a/core/modules/map.rs b/core/modules/map.rs
index d038950..a62a80b 100644
--- a/core/modules/map.rs
+++ b/core/modules/map.rs
@@ -339,9 +339,7 @@ impl ModuleMap {
 
     let module_id = match module_type {
       ModuleType::JavaScript => {
-        let code =
-          ModuleSource::get_string_source(module_url_found.as_str(), code)
-            .map_err(ModuleError::Other)?;
+        let code = ModuleSource::get_string_source(code);
 
         let (code_cache_info, module_url_found) =
           if let Some(code_cache) = code_cache {
@@ -379,9 +377,7 @@ impl ModuleMap {
         )));
       }
       ModuleType::Json => {
-        let code =
-          ModuleSource::get_string_source(module_url_found.as_str(), code)
-            .map_err(ModuleError::Other)?;
+        let code = ModuleSource::get_string_source(code);
         self.new_json_module(scope, module_url_found, code)?
       }
       ModuleType::Other(module_type) => {
@@ -1757,7 +1753,7 @@ impl ModuleMap {
     self.lazy_load_es_module_with_code(
       scope,
       module_specifier,
-      ModuleSource::get_string_source(specifier.as_str(), source.code)?,
+      ModuleSource::get_string_source(source.code),
       if let Some(code_cache) = source.code_cache {
         let loader = self.loader.borrow().clone();
         Some(CodeCacheInfo {
diff --git a/core/modules/mod.rs b/core/modules/mod.rs
index 3ba8064..3ab0c18 100644
--- a/core/modules/mod.rs
+++ b/core/modules/mod.rs
@@ -5,7 +5,6 @@ use crate::fast_string::FastString;
 use crate::module_specifier::ModuleSpecifier;
 use crate::FastStaticString;
 use anyhow::bail;
-use anyhow::Context;
 use anyhow::Error;
 use serde::Deserialize;
 use serde::Serialize;
@@ -459,17 +458,14 @@ impl ModuleSource {
     }
   }
 
-  pub fn get_string_source(
-    specifier: &str,
-    code: ModuleSourceCode,
-  ) -> Result<ModuleCodeString, AnyError> {
+  pub fn get_string_source(code: ModuleSourceCode) -> ModuleCodeString {
     match code {
-      ModuleSourceCode::String(code) => Ok(code),
+      ModuleSourceCode::String(code) => code,
       ModuleSourceCode::Bytes(bytes) => {
-        let str_ = String::from_utf8(bytes.to_vec()).with_context(|| {
-          format!("Can't convert source code to string for {}", specifier)
-        })?;
-        Ok(ModuleCodeString::from(str_))
+        match String::from_utf8_lossy(bytes.as_bytes()) {
+          Cow::Borrowed(s) => ModuleCodeString::from(s.to_owned()),
+          Cow::Owned(s) => ModuleCodeString::from(s),
+        }
       }
     }
   }


Test patch:
diff --git a/core/modules/tests.rs b/core/modules/tests.rs
index 2fd5472..9adf65f 100644
--- a/core/modules/tests.rs
+++ b/core/modules/tests.rs
@@ -1914,3 +1914,14 @@ fn ext_module_loader_relative() {
     assert_eq!(result.as_str(), expected);
   }
 }
+
+#[test]
+fn invalid_utf8_module() {
+  let get_string_source = ModuleSource::get_string_source(
+    ModuleSourceCode::Bytes(ModuleCodeBytes::Static(b"// \xFE\xFE\xFF\xFF")),
+  );
+  assert_eq!(
+    get_string_source,
+    FastString::from_static("// \u{FFFD}\u{FFFD}\u{FFFD}\u{FFFD}")
+  );
+}