fix(common): Workaround the Arc and rkyv issue (#7321)

**Description:**

Attempt to workaround #7238.

Originally I thought this is related with oom or memory layout, then realized actual deserialization error occurs in weird position - it tries to deserialize BytePos (which is obvious type) and it fails. It made me think maybe a property next to the struct layout have some unexpected behavior, notably Arc<String>.

PR applies same workaround as Atom does, and it seems to at least pass swc-coverage-instrument's usecases. May need bit more verification with other plugins to see if we can call this out as reliable workaround.
This commit is contained in:
OJ Kwon 2023-04-24 02:23:31 -07:00 committed by GitHub
parent 51f3840609
commit 577f81ec40
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 0 deletions

View File

@ -816,6 +816,55 @@ impl Sub<BytePos> for NonNarrowChar {
}
}
/// This is not a public interface, workaround for https://github.com/swc-project/swc/issues/7238
#[doc(hidden)]
#[cfg(feature = "rkyv-impl")]
#[derive(Debug, Clone, Copy)]
pub struct EncodeArcString;
#[cfg(feature = "rkyv-impl")]
impl rkyv::with::ArchiveWith<Lrc<String>> for EncodeArcString {
type Archived = rkyv::Archived<String>;
type Resolver = rkyv::Resolver<String>;
unsafe fn resolve_with(
field: &Lrc<String>,
pos: usize,
resolver: Self::Resolver,
out: *mut Self::Archived,
) {
let s = field.to_string();
rkyv::Archive::resolve(&s, pos, resolver, out);
}
}
#[cfg(feature = "rkyv-impl")]
impl<S> rkyv::with::SerializeWith<Lrc<String>, S> for EncodeArcString
where
S: ?Sized + rkyv::ser::Serializer,
{
fn serialize_with(field: &Lrc<String>, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
rkyv::string::ArchivedString::serialize_from_str(field, serializer)
}
}
#[cfg(feature = "rkyv-impl")]
impl<D> rkyv::with::DeserializeWith<rkyv::Archived<String>, Lrc<String>, D> for EncodeArcString
where
D: ?Sized + rkyv::Fallible,
{
fn deserialize_with(
field: &rkyv::Archived<String>,
deserializer: &mut D,
) -> Result<Lrc<String>, D::Error> {
use rkyv::Deserialize;
let s: String = field.deserialize(deserializer)?;
Ok(s.into())
}
}
/// A single source in the SourceMap.
#[cfg_attr(
any(feature = "rkyv-impl"),
@ -836,6 +885,7 @@ pub struct SourceFile {
/// Indicates which crate this `SourceFile` was imported from.
pub crate_of_origin: u32,
/// The complete source code
#[cfg_attr(any(feature = "rkyv-impl"), with(EncodeArcString))]
pub src: Lrc<String>,
/// The source code's hash
pub src_hash: u128,

View File

@ -9,6 +9,19 @@ use swc_common::plugin::serialized::{deserialize_from_ptr, PluginSerializedBytes
)]
pub struct AllocatedBytesPtr(pub u32, pub u32);
#[cfg(target_arch = "wasm32")]
extern "C" {
fn __free(ptr: *mut u8, size: i32) -> i32;
}
#[cfg(target_arch = "wasm32")]
impl Drop for AllocatedBytesPtr {
fn drop(&mut self) {
unsafe {
__free(self.0 as _, self.1 as _);
}
}
}
#[cfg(not(feature = "__rkyv"))]
fn read_returned_result_from_host_inner<F>(f: F) -> Option<AllocatedBytesPtr> {
unimplemented!("Plugin proxy does not work without serialization support")