mirror of
https://github.com/swc-project/swc.git
synced 2024-11-29 11:47:21 +03:00
feat(plugin): Implement plugin api for comments (#4229)
This commit is contained in:
parent
f39895e563
commit
6ea66cf001
@ -57,6 +57,15 @@ impl Serialized {
|
|||||||
Serialized { field: vec }
|
Serialized { field: vec }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Not an actual trait Into impl: simple wrapper to deserialize<T>:expect()
|
||||||
|
pub fn into<T>(self) -> T
|
||||||
|
where
|
||||||
|
T: rkyv::Archive,
|
||||||
|
T::Archived: rkyv::Deserialize<T, rkyv::Infallible>,
|
||||||
|
{
|
||||||
|
Serialized::deserialize(&self).expect("Should able to deserialize")
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(clippy::should_implement_trait)]
|
#[allow(clippy::should_implement_trait)]
|
||||||
pub fn as_ref(&self) -> &rkyv::AlignedVec {
|
pub fn as_ref(&self) -> &rkyv::AlignedVec {
|
||||||
&self.field
|
&self.field
|
||||||
|
@ -7,7 +7,7 @@ pub use swc_common::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub mod comments {
|
pub mod comments {
|
||||||
pub use swc_common::comments::Comments;
|
pub use swc_common::comments::{Comment, CommentKind, Comments};
|
||||||
pub use swc_plugin_comments::PluginCommentsProxy;
|
pub use swc_plugin_comments::PluginCommentsProxy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,22 @@ use swc_common::{
|
|||||||
BytePos,
|
BytePos,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
fn __copy_comment_to_host_env(bytes_ptr: i32, bytes_ptr_len: i32);
|
||||||
|
fn __add_leading_comment_proxy(byte_pos: u32);
|
||||||
|
fn __add_leading_comments_proxy(byte_pos: u32);
|
||||||
|
fn __has_leading_comments_proxy(byte_pos: u32) -> i32;
|
||||||
|
fn __move_leading_comments_proxy(from_byte_pos: u32, to_byte_pos: u32);
|
||||||
|
fn __take_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
||||||
fn __get_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
fn __get_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
||||||
|
fn __add_trailing_comment_proxy(byte_pos: u32);
|
||||||
|
fn __add_trailing_comments_proxy(byte_pos: u32);
|
||||||
|
fn __has_trailing_comments_proxy(byte_pos: u32) -> i32;
|
||||||
|
fn __move_trailing_comments_proxy(from_byte_pos: u32, to_byte_pos: u32);
|
||||||
|
fn __take_trailing_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
||||||
|
fn __get_trailing_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
||||||
|
fn __add_pure_comment_proxy(byte_pos: u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A struct to exchance allocated Vec<Comment> between memory spaces.
|
/// A struct to exchance allocated Vec<Comment> between memory spaces.
|
||||||
@ -28,28 +41,43 @@ pub struct CommentsVecPtr(pub i32, pub i32);
|
|||||||
pub struct PluginCommentsProxy;
|
pub struct PluginCommentsProxy;
|
||||||
|
|
||||||
#[cfg(feature = "plugin-mode")]
|
#[cfg(feature = "plugin-mode")]
|
||||||
impl Comments for PluginCommentsProxy {
|
impl PluginCommentsProxy {
|
||||||
fn add_leading(&self, pos: BytePos, cmt: Comment) {
|
/// Copy guest memory's struct into host via CommentHostEnvironment's
|
||||||
unimplemented!("not implemented yet");
|
/// comment_buffer as serialized to pass param from guest to the host for
|
||||||
|
/// the fn like add_leading*.
|
||||||
|
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
|
||||||
|
fn allocate_comments_buffer_to_host<T>(&self, value: &T)
|
||||||
|
where
|
||||||
|
T: rkyv::Serialize<rkyv::ser::serializers::AllocSerializer<512>>,
|
||||||
|
{
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
let serialized = Serialized::serialize(value).expect("Should able to serialize value");
|
||||||
|
let serialized_comment_ptr_ref = serialized.as_ref();
|
||||||
|
unsafe {
|
||||||
|
// We need to copy PluginCommentProxy's param for add_leading (Comment, or
|
||||||
|
// Vec<Comment>) to the host, before calling proxy to the host. This'll fill in
|
||||||
|
// CommentHostEnvironment's buffer, subsequent proxy call will read &
|
||||||
|
// deserialize it.
|
||||||
|
__copy_comment_to_host_env(
|
||||||
|
serialized_comment_ptr_ref.as_ptr() as _,
|
||||||
|
serialized_comment_ptr_ref
|
||||||
|
.len()
|
||||||
|
.try_into()
|
||||||
|
.expect("Should able to convert ptr length"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_leading_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
/// Utiilty wrapper to call host fn which returns a Comment or Vec<Comment>.
|
||||||
unimplemented!("not implemented yet");
|
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
|
||||||
}
|
fn read_returned_comments_from_host<F, R>(&self, f: F) -> Option<R>
|
||||||
|
where
|
||||||
fn has_leading(&self, pos: BytePos) -> bool {
|
F: FnOnce(i32) -> i32,
|
||||||
unimplemented!("not implemented yet");
|
R: rkyv::Archive,
|
||||||
}
|
R::Archived: rkyv::Deserialize<R, rkyv::Infallible>,
|
||||||
|
{
|
||||||
fn move_leading(&self, from: BytePos, to: BytePos) {
|
|
||||||
unimplemented!("not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn take_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
|
||||||
unimplemented!("not implemented yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
|
||||||
// Allocate CommentsVecPtr to get return value from the host
|
// Allocate CommentsVecPtr to get return value from the host
|
||||||
let comments_vec_ptr = CommentsVecPtr(0, 0);
|
let comments_vec_ptr = CommentsVecPtr(0, 0);
|
||||||
let serialized_comments_vec_ptr = Serialized::serialize(&comments_vec_ptr)
|
let serialized_comments_vec_ptr = Serialized::serialize(&comments_vec_ptr)
|
||||||
@ -58,18 +86,20 @@ impl Comments for PluginCommentsProxy {
|
|||||||
let serialized_comments_vec_ptr_raw_ptr = serialized_comments_vec_ptr_ref.as_ptr();
|
let serialized_comments_vec_ptr_raw_ptr = serialized_comments_vec_ptr_ref.as_ptr();
|
||||||
let serialized_comments_vec_ptr_raw_len = serialized_comments_vec_ptr_ref.len();
|
let serialized_comments_vec_ptr_raw_len = serialized_comments_vec_ptr_ref.len();
|
||||||
|
|
||||||
#[cfg(target = "wasm32")]
|
#[cfg(target_arch = "wasm32")]
|
||||||
{
|
{
|
||||||
let ret = unsafe {
|
let ret = f(serialized_comments_vec_ptr_raw_ptr as _);
|
||||||
__get_leading_comments_proxy(pos.0, serialized_comments_vec_ptr_raw_ptr as _)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
// Host fn call completes: by contract in commments_proxy, if return value is 0
|
||||||
|
// we know there's no value to read. Otherwise, we know host filled in
|
||||||
|
// CommentsVecPtr to the pointer for the actual value for the
|
||||||
|
// results.
|
||||||
if ret == 0 {
|
if ret == 0 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// First, reconstruct CommentsVecPtr to reveal ptr to the allocated
|
// Now reconstruct CommentsVecPtr to reveal ptr to the allocated
|
||||||
// Vec<Comments>
|
// Vec<Comments>
|
||||||
let comments_vec_ptr: CommentsVecPtr = unsafe {
|
let comments_vec_ptr: CommentsVecPtr = unsafe {
|
||||||
Serialized::deserialize_from_ptr(
|
Serialized::deserialize_from_ptr(
|
||||||
@ -81,54 +111,135 @@ impl Comments for PluginCommentsProxy {
|
|||||||
.expect("Should able to deserialize CommentsVecPtr")
|
.expect("Should able to deserialize CommentsVecPtr")
|
||||||
};
|
};
|
||||||
|
|
||||||
// Using CommentsVecPtr's value, reconstruct actual Vec<Comments>
|
// Using CommentsVecPtr's value, reconstruct actual Comment, or Vec<Comments>
|
||||||
Some(unsafe {
|
Some(unsafe {
|
||||||
Serialized::deserialize_from_ptr(comments_vec_ptr.0 as _, comments_vec_ptr.1)
|
Serialized::deserialize_from_ptr(comments_vec_ptr.0 as _, comments_vec_ptr.1)
|
||||||
.expect("Returned comments should be serializable")
|
.expect("Returned comments should be serializable")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "plugin-mode")]
|
||||||
|
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
|
||||||
|
impl Comments for PluginCommentsProxy {
|
||||||
|
fn add_leading(&self, pos: BytePos, cmt: Comment) {
|
||||||
|
self.allocate_comments_buffer_to_host(&cmt);
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__add_leading_comment_proxy(pos.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_leading_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
||||||
|
self.allocate_comments_buffer_to_host(&comments);
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__add_leading_comments_proxy(pos.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_leading(&self, pos: BytePos) -> bool {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
if unsafe { __has_leading_comments_proxy(pos.0) } == 0 {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_leading(&self, from: BytePos, to: BytePos) {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__move_leading_comments_proxy(from.0, to.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn take_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
return self.read_returned_comments_from_host(|serialized_ptr| unsafe {
|
||||||
|
__take_leading_comments_proxy(pos.0, serialized_ptr)
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_leading(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
return self.read_returned_comments_from_host(|serialized_ptr| unsafe {
|
||||||
|
__get_leading_comments_proxy(pos.0, serialized_ptr)
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
fn add_trailing(&self, pos: BytePos, cmt: Comment) {
|
fn add_trailing(&self, pos: BytePos, cmt: Comment) {
|
||||||
unimplemented!("not implemented yet");
|
self.allocate_comments_buffer_to_host(&cmt);
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__add_trailing_comment_proxy(pos.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_trailing_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
fn add_trailing_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
||||||
unimplemented!("not implemented yet");
|
self.allocate_comments_buffer_to_host(&comments);
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__add_trailing_comments_proxy(pos.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn has_trailing(&self, pos: BytePos) -> bool {
|
fn has_trailing(&self, pos: BytePos) -> bool {
|
||||||
unimplemented!("not implemented yet");
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
{
|
||||||
|
if unsafe { __has_trailing_comments_proxy(pos.0) } == 0 {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn move_trailing(&self, from: BytePos, to: BytePos) {
|
fn move_trailing(&self, from: BytePos, to: BytePos) {
|
||||||
unimplemented!("not implemented yet");
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
unsafe {
|
||||||
|
__move_trailing_comments_proxy(from.0, to.0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn take_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
fn take_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||||
unimplemented!("not implemented yet");
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
return self.read_returned_comments_from_host(|serialized_ptr| unsafe {
|
||||||
|
__take_trailing_comments_proxy(pos.0, serialized_ptr)
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
fn get_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||||
unimplemented!("not implemented yet");
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
return self.read_returned_comments_from_host(|serialized_ptr| unsafe {
|
||||||
|
__get_trailing_comments_proxy(pos.0, serialized_ptr)
|
||||||
|
});
|
||||||
|
|
||||||
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_pure_comment(&self, pos: BytePos) {
|
fn add_pure_comment(&self, pos: BytePos) {
|
||||||
unimplemented!("not implemented yet");
|
#[cfg(target_arch = "wasm32")]
|
||||||
}
|
|
||||||
|
|
||||||
fn with_leading<F, Ret>(&self, pos: BytePos, f: F) -> Ret
|
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
F: FnOnce(&[Comment]) -> Ret,
|
|
||||||
{
|
{
|
||||||
unimplemented!("not implemented yet");
|
unsafe {
|
||||||
}
|
__add_pure_comment_proxy(pos.0);
|
||||||
|
}
|
||||||
fn with_trailing<F, Ret>(&self, pos: BytePos, f: F) -> Ret
|
}
|
||||||
where
|
|
||||||
Self: Sized,
|
|
||||||
F: FnOnce(&[Comment]) -> Ret,
|
|
||||||
{
|
|
||||||
unimplemented!("not implemented yet");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,29 +1,25 @@
|
|||||||
use std::sync::Arc;
|
use wasmer::{LazyInit, Memory};
|
||||||
|
|
||||||
use parking_lot::Mutex;
|
|
||||||
use wasmer::{LazyInit, Memory, NativeFunc};
|
|
||||||
|
|
||||||
#[derive(wasmer::WasmerEnv, Clone)]
|
|
||||||
/// An external enviornment state imported (declared in host, injected into
|
/// An external enviornment state imported (declared in host, injected into
|
||||||
/// guest) fn can access. This'll allow host access updated state via plugin's
|
/// guest) fn can access. This'll allow host to read from updated state from
|
||||||
/// transform.
|
/// guest.
|
||||||
|
///
|
||||||
|
/// This is `base` environment exposes guest's memory space only. For other
|
||||||
|
/// calls requires additional data to be set in the host, separate
|
||||||
|
/// hostenvironments are decalred. Refer `CommentsHostEnvironment` for an
|
||||||
|
/// example.
|
||||||
|
///
|
||||||
/// ref: https://docs.wasmer.io/integrations/examples/host-functions#declaring-the-data
|
/// ref: https://docs.wasmer.io/integrations/examples/host-functions#declaring-the-data
|
||||||
pub struct HostEnvironment {
|
#[derive(wasmer::WasmerEnv, Clone)]
|
||||||
|
pub struct BaseHostEnvironment {
|
||||||
#[wasmer(export)]
|
#[wasmer(export)]
|
||||||
pub memory: wasmer::LazyInit<Memory>,
|
pub memory: wasmer::LazyInit<Memory>,
|
||||||
pub transform_result: Arc<Mutex<Vec<u8>>>,
|
|
||||||
/// Attached imported fn `__alloc` to the hostenvironment to allow any other
|
|
||||||
/// imported fn can allocate guest's memory space from host runtime.
|
|
||||||
#[wasmer(export(name = "__alloc"))]
|
|
||||||
pub alloc_guest_memory: LazyInit<NativeFunc<u32, i32>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostEnvironment {
|
impl BaseHostEnvironment {
|
||||||
pub fn new(transform_result: &Arc<Mutex<Vec<u8>>>) -> HostEnvironment {
|
pub fn new() -> BaseHostEnvironment {
|
||||||
HostEnvironment {
|
BaseHostEnvironment {
|
||||||
memory: LazyInit::default(),
|
memory: LazyInit::new(),
|
||||||
transform_result: transform_result.clone(),
|
|
||||||
alloc_guest_memory: LazyInit::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,118 @@
|
|||||||
use swc_common::{comments::Comments, plugin::Serialized, BytePos};
|
use std::sync::Arc;
|
||||||
use swc_plugin_comments::{CommentsVecPtr, HostCommentsStorage, COMMENTS};
|
|
||||||
|
|
||||||
use crate::{host_environment::HostEnvironment, memory_interop::write_into_memory_view};
|
use parking_lot::Mutex;
|
||||||
|
use swc_common::{
|
||||||
|
comments::{Comments, SingleThreadedComments},
|
||||||
|
plugin::Serialized,
|
||||||
|
BytePos,
|
||||||
|
};
|
||||||
|
use swc_plugin_comments::{CommentsVecPtr, COMMENTS};
|
||||||
|
use wasmer::{LazyInit, Memory, NativeFunc};
|
||||||
|
|
||||||
/// Ask to get leading_comments from currently scoped comments held by
|
use crate::memory_interop::{copy_bytes_into_host, write_into_memory_view};
|
||||||
/// HostCommentsStorage.
|
|
||||||
///
|
/// External environment state for imported (declared in host, injected into
|
||||||
/// Returns 1 if operation success with Some(Vec<Comments>), 0 otherwise.
|
/// guest) fn for comments proxy.
|
||||||
/// Allocated results should be read through CommentsPtr.
|
#[derive(wasmer::WasmerEnv, Clone)]
|
||||||
pub fn get_leading_comments_proxy(
|
pub struct CommentHostEnvironment {
|
||||||
env: &HostEnvironment,
|
#[wasmer(export)]
|
||||||
byte_pos: u32,
|
pub memory: wasmer::LazyInit<Memory>,
|
||||||
allocated_ret_ptr: i32,
|
/// Attached imported fn `__alloc` to the hostenvironment to allow any other
|
||||||
) -> i32 {
|
/// imported fn can allocate guest's memory space from host runtime.
|
||||||
if let Some(memory) = env.memory_ref() {
|
#[wasmer(export(name = "__alloc"))]
|
||||||
if let Some(alloc_guest_memory) = env.alloc_guest_memory_ref() {
|
pub alloc_guest_memory: LazyInit<NativeFunc<u32, i32>>,
|
||||||
if !COMMENTS.is_set() {
|
/// A buffer to `Comment`, or `Vec<Comment>` plugin need to pass to the host
|
||||||
return 0;
|
/// to perform mutable comment operations like `add_leading, or
|
||||||
|
/// add_leading_comments`. This is vec to serialized bytes, doesn't
|
||||||
|
/// distinguish if it's Vec<Comment> or not. Host should perform
|
||||||
|
/// typed deserialization accordingly.
|
||||||
|
pub mutable_comment_buffer: Arc<Mutex<Vec<u8>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
return COMMENTS.with(|storage: &HostCommentsStorage| {
|
impl CommentHostEnvironment {
|
||||||
|
pub fn new(mutable_comment_buffer: &Arc<Mutex<Vec<u8>>>) -> CommentHostEnvironment {
|
||||||
|
CommentHostEnvironment {
|
||||||
|
memory: LazyInit::default(),
|
||||||
|
alloc_guest_memory: LazyInit::default(),
|
||||||
|
mutable_comment_buffer: mutable_comment_buffer.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Copy given serialized byte into host's comment buffer, subsequent proxy call
|
||||||
|
/// in the host can read it.
|
||||||
|
pub fn copy_comment_to_host_env(env: &CommentHostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||||
|
if let Some(memory) = env.memory_ref() {
|
||||||
|
(*env.mutable_comment_buffer.lock()) =
|
||||||
|
copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Utility fn to unwrap necessary values for the comments fn operation when fn
|
||||||
|
/// needs to return values.
|
||||||
|
fn unwrap_comments_storage_or_default<F, R>(f: F, default: R) -> R
|
||||||
|
where
|
||||||
|
F: FnOnce(&SingleThreadedComments) -> R,
|
||||||
|
{
|
||||||
|
if !COMMENTS.is_set() {
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
|
||||||
|
COMMENTS.with(|storage| {
|
||||||
if let Some(comments) = &storage.inner {
|
if let Some(comments) = &storage.inner {
|
||||||
let leading_comments = comments.get_leading(BytePos(byte_pos));
|
f(comments)
|
||||||
if let Some(leading_comments) = leading_comments {
|
} else {
|
||||||
let serialized_leading_comments_vec_bytes =
|
default
|
||||||
Serialized::serialize(&leading_comments)
|
}
|
||||||
.expect("Should be serializable");
|
})
|
||||||
|
}
|
||||||
|
|
||||||
let serialized_bytes_len =
|
/// Utility fn to unwrap necessary values for the comments fn operation when fn
|
||||||
serialized_leading_comments_vec_bytes.as_ref().len();
|
/// does not need to return values.
|
||||||
|
fn unwrap_comments_storage<F>(f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&SingleThreadedComments),
|
||||||
|
{
|
||||||
|
unwrap_comments_storage_or_default(
|
||||||
|
|comments| {
|
||||||
|
f(comments);
|
||||||
|
None
|
||||||
|
},
|
||||||
|
None as Option<i32>,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
let (allocated_ptr, allocated_ptr_len) = write_into_memory_view(
|
/// Utility fn to unwrap necessary values for the commments, as well as host
|
||||||
memory,
|
/// environment's state.
|
||||||
&serialized_leading_comments_vec_bytes,
|
fn unwrap_comments_storage_with_env<F, R>(env: &CommentHostEnvironment, f: F, default: R) -> R
|
||||||
|_| {
|
where
|
||||||
|
F: FnOnce(&SingleThreadedComments, &Memory, &NativeFunc<u32, i32>) -> R,
|
||||||
|
{
|
||||||
|
if let Some(memory) = env.memory_ref() {
|
||||||
|
if let Some(alloc_guest_memory) = env.alloc_guest_memory_ref() {
|
||||||
|
return unwrap_comments_storage_or_default(
|
||||||
|
|comments| f(comments, memory, alloc_guest_memory),
|
||||||
|
default,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set `return` value to pass into guest from functions returning values with
|
||||||
|
/// non-deterministic size like `Vec<Comment>`. Guest pre-allocates a struct to
|
||||||
|
/// contain ptr to the value, host in here allocates guest memory for the actual
|
||||||
|
/// value then returns its ptr with length to the preallocated struct.
|
||||||
|
fn allocate_return_values_into_guest(
|
||||||
|
memory: &Memory,
|
||||||
|
alloc_guest_memory: &NativeFunc<u32, i32>,
|
||||||
|
allocated_ret_ptr: i32,
|
||||||
|
serialized_bytes: &Serialized,
|
||||||
|
) {
|
||||||
|
let serialized_bytes_len = serialized_bytes.as_ref().len();
|
||||||
|
|
||||||
|
let (allocated_ptr, allocated_ptr_len) =
|
||||||
|
write_into_memory_view(memory, serialized_bytes, |_| {
|
||||||
// In most cases our host-plugin tranmpoline works in a way that
|
// In most cases our host-plugin tranmpoline works in a way that
|
||||||
// plugin pre-allocates
|
// plugin pre-allocates
|
||||||
// memory before calling host imported fn. But in case of
|
// memory before calling host imported fn. But in case of
|
||||||
@ -48,25 +127,205 @@ pub fn get_leading_comments_proxy(
|
|||||||
.expect("Should be able to convert size"),
|
.expect("Should be able to convert size"),
|
||||||
)
|
)
|
||||||
.expect("Should able to allocate memory in the plugin")
|
.expect("Should able to allocate memory in the plugin")
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
// Retuning (allocated_ptr, len) into caller (plugin)
|
// Retuning (allocated_ptr, len) into caller (plugin)
|
||||||
let comment_ptr_serialized = Serialized::serialize(&CommentsVecPtr(
|
let comment_ptr_serialized =
|
||||||
allocated_ptr,
|
Serialized::serialize(&CommentsVecPtr(allocated_ptr, allocated_ptr_len))
|
||||||
allocated_ptr_len,
|
|
||||||
))
|
|
||||||
.expect("Should be serializable");
|
.expect("Should be serializable");
|
||||||
|
|
||||||
write_into_memory_view(memory, &comment_ptr_serialized, |_| {
|
write_into_memory_view(memory, &comment_ptr_serialized, |_| allocated_ret_ptr);
|
||||||
allocated_ret_ptr
|
|
||||||
});
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
0
|
/// Common logics for add_*_comment/comments.
|
||||||
|
fn add_comments_inner<F>(env: &CommentHostEnvironment, byte_pos: u32, f: F)
|
||||||
|
where
|
||||||
|
F: FnOnce(&SingleThreadedComments, BytePos, Serialized),
|
||||||
|
{
|
||||||
|
unwrap_comments_storage(|comments| {
|
||||||
|
let byte_pos = BytePos(byte_pos);
|
||||||
|
// PluginCommentProxy in the guest should've copied buffer already
|
||||||
|
let comment_byte = &mut (*env.mutable_comment_buffer.lock());
|
||||||
|
let serialized = Serialized::new_for_plugin(
|
||||||
|
comment_byte,
|
||||||
|
comment_byte
|
||||||
|
.len()
|
||||||
|
.try_into()
|
||||||
|
.expect("Should able to convert ptr length"),
|
||||||
|
);
|
||||||
|
|
||||||
|
f(comments, byte_pos, serialized);
|
||||||
|
|
||||||
|
// This is not strictly required, but will help to ensure to access previous
|
||||||
|
// call's buffer when we make some mistakes for the execution order.
|
||||||
|
comment_byte.clear();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_leading_comment_proxy(env: &CommentHostEnvironment, byte_pos: u32) {
|
||||||
|
add_comments_inner(env, byte_pos, |comments, byte_pos, serialized| {
|
||||||
|
comments.add_leading(byte_pos, serialized.into());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_leading_comments_proxy(env: &CommentHostEnvironment, byte_pos: u32) {
|
||||||
|
add_comments_inner(env, byte_pos, |comments, byte_pos, serialized| {
|
||||||
|
comments.add_leading_comments(byte_pos, serialized.into());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_leading_comments_proxy(byte_pos: u32) -> i32 {
|
||||||
|
unwrap_comments_storage_or_default(|comments| comments.has_leading(BytePos(byte_pos)) as i32, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_leading_comments_proxy(from_byte_pos: u32, to_byte_pos: u32) {
|
||||||
|
unwrap_comments_storage(|comments| {
|
||||||
|
comments.move_leading(BytePos(from_byte_pos), BytePos(to_byte_pos))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_leading_comments_proxy(
|
||||||
|
env: &CommentHostEnvironment,
|
||||||
|
byte_pos: u32,
|
||||||
|
allocated_ret_ptr: i32,
|
||||||
|
) -> i32 {
|
||||||
|
unwrap_comments_storage_with_env(
|
||||||
|
env,
|
||||||
|
|comments, memory, alloc_guest_memory| {
|
||||||
|
let leading_comments = comments.take_leading(BytePos(byte_pos));
|
||||||
|
if let Some(leading_comments) = leading_comments {
|
||||||
|
let serialized_leading_comments_vec_bytes =
|
||||||
|
Serialized::serialize(&leading_comments).expect("Should be serializable");
|
||||||
|
|
||||||
|
allocate_return_values_into_guest(
|
||||||
|
memory,
|
||||||
|
alloc_guest_memory,
|
||||||
|
allocated_ret_ptr,
|
||||||
|
&serialized_leading_comments_vec_bytes,
|
||||||
|
);
|
||||||
|
1
|
||||||
|
} else {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Ask to get leading_comments from currently scoped comments held by
|
||||||
|
/// HostCommentsStorage.
|
||||||
|
///
|
||||||
|
/// Returns 1 if operation success with Some(Vec<Comments>), 0 otherwise.
|
||||||
|
/// Allocated results should be read through CommentsPtr.
|
||||||
|
pub fn get_leading_comments_proxy(
|
||||||
|
env: &CommentHostEnvironment,
|
||||||
|
byte_pos: u32,
|
||||||
|
allocated_ret_ptr: i32,
|
||||||
|
) -> i32 {
|
||||||
|
unwrap_comments_storage_with_env(
|
||||||
|
env,
|
||||||
|
|comments, memory, alloc_guest_memory| {
|
||||||
|
let leading_comments = comments.get_leading(BytePos(byte_pos));
|
||||||
|
if let Some(leading_comments) = leading_comments {
|
||||||
|
let serialized_leading_comments_vec_bytes =
|
||||||
|
Serialized::serialize(&leading_comments).expect("Should be serializable");
|
||||||
|
|
||||||
|
allocate_return_values_into_guest(
|
||||||
|
memory,
|
||||||
|
alloc_guest_memory,
|
||||||
|
allocated_ret_ptr,
|
||||||
|
&serialized_leading_comments_vec_bytes,
|
||||||
|
);
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_trailing_comment_proxy(env: &CommentHostEnvironment, byte_pos: u32) {
|
||||||
|
add_comments_inner(env, byte_pos, |comments, byte_pos, serialized| {
|
||||||
|
comments.add_trailing(byte_pos, serialized.into());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_trailing_comments_proxy(env: &CommentHostEnvironment, byte_pos: u32) {
|
||||||
|
add_comments_inner(env, byte_pos, |comments, byte_pos, serialized| {
|
||||||
|
comments.add_trailing_comments(byte_pos, serialized.into());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn has_trailing_comments_proxy(byte_pos: u32) -> i32 {
|
||||||
|
unwrap_comments_storage_or_default(
|
||||||
|
|comments| comments.has_trailing(BytePos(byte_pos)) as i32,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn move_trailing_comments_proxy(from_byte_pos: u32, to_byte_pos: u32) {
|
||||||
|
unwrap_comments_storage(|comments| {
|
||||||
|
comments.move_trailing(BytePos(from_byte_pos), BytePos(to_byte_pos))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn take_trailing_comments_proxy(
|
||||||
|
env: &CommentHostEnvironment,
|
||||||
|
byte_pos: u32,
|
||||||
|
allocated_ret_ptr: i32,
|
||||||
|
) -> i32 {
|
||||||
|
unwrap_comments_storage_with_env(
|
||||||
|
env,
|
||||||
|
|comments, memory, alloc_guest_memory| {
|
||||||
|
let trailing_comments = comments.take_trailing(BytePos(byte_pos));
|
||||||
|
if let Some(leading_comments) = trailing_comments {
|
||||||
|
let serialized_leading_comments_vec_bytes =
|
||||||
|
Serialized::serialize(&leading_comments).expect("Should be serializable");
|
||||||
|
|
||||||
|
allocate_return_values_into_guest(
|
||||||
|
memory,
|
||||||
|
alloc_guest_memory,
|
||||||
|
allocated_ret_ptr,
|
||||||
|
&serialized_leading_comments_vec_bytes,
|
||||||
|
);
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_trailing_comments_proxy(
|
||||||
|
env: &CommentHostEnvironment,
|
||||||
|
byte_pos: u32,
|
||||||
|
allocated_ret_ptr: i32,
|
||||||
|
) -> i32 {
|
||||||
|
unwrap_comments_storage_with_env(
|
||||||
|
env,
|
||||||
|
|comments, memory, alloc_guest_memory| {
|
||||||
|
let trailing_comments = comments.get_trailing(BytePos(byte_pos));
|
||||||
|
if let Some(leading_comments) = trailing_comments {
|
||||||
|
let serialized_leading_comments_vec_bytes =
|
||||||
|
Serialized::serialize(&leading_comments).expect("Should be serializable");
|
||||||
|
|
||||||
|
allocate_return_values_into_guest(
|
||||||
|
memory,
|
||||||
|
alloc_guest_memory,
|
||||||
|
allocated_ret_ptr,
|
||||||
|
&serialized_leading_comments_vec_bytes,
|
||||||
|
);
|
||||||
|
1
|
||||||
|
} else {
|
||||||
|
0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_pure_comment_proxy(byte_pos: u32) {
|
||||||
|
unwrap_comments_storage(|comments| comments.add_pure_comment(BytePos(byte_pos)));
|
||||||
|
}
|
||||||
|
@ -3,9 +3,9 @@ use swc_common::{
|
|||||||
plugin::Serialized,
|
plugin::Serialized,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{host_environment::HostEnvironment, memory_interop::copy_bytes_into_host};
|
use crate::{host_environment::BaseHostEnvironment, memory_interop::copy_bytes_into_host};
|
||||||
|
|
||||||
pub fn emit_diagnostics(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
pub fn emit_diagnostics(env: &BaseHostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||||
if let Some(memory) = env.memory_ref() {
|
if let Some(memory) = env.memory_ref() {
|
||||||
if HANDLER.is_set() {
|
if HANDLER.is_set() {
|
||||||
HANDLER.with(|handler| {
|
HANDLER.with(|handler| {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use swc_common::{hygiene::MutableMarkContext, plugin::Serialized, Mark, SyntaxContext};
|
use swc_common::{hygiene::MutableMarkContext, plugin::Serialized, Mark, SyntaxContext};
|
||||||
|
|
||||||
use crate::{host_environment::HostEnvironment, memory_interop::write_into_memory_view};
|
use crate::{host_environment::BaseHostEnvironment, memory_interop::write_into_memory_view};
|
||||||
|
|
||||||
/// A proxy to Mark::fresh() that can be used in plugin.
|
/// A proxy to Mark::fresh() that can be used in plugin.
|
||||||
/// This it not direcly called by plugin, instead `impl Mark` will selectively
|
/// This it not direcly called by plugin, instead `impl Mark` will selectively
|
||||||
@ -27,7 +27,7 @@ pub fn mark_set_builtin_proxy(self_mark: u32, is_builtin: u32) {
|
|||||||
/// Inside of guest context, once this host function returns it'll assign params
|
/// Inside of guest context, once this host function returns it'll assign params
|
||||||
/// with return value accordingly.
|
/// with return value accordingly.
|
||||||
pub fn mark_is_descendant_of_proxy(
|
pub fn mark_is_descendant_of_proxy(
|
||||||
env: &HostEnvironment,
|
env: &BaseHostEnvironment,
|
||||||
self_mark: u32,
|
self_mark: u32,
|
||||||
ancestor: u32,
|
ancestor: u32,
|
||||||
allocated_ptr: i32,
|
allocated_ptr: i32,
|
||||||
@ -49,7 +49,7 @@ pub fn mark_is_descendant_of_proxy(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mark_least_ancestor_proxy(env: &HostEnvironment, a: u32, b: u32, allocated_ptr: i32) {
|
pub fn mark_least_ancestor_proxy(env: &BaseHostEnvironment, a: u32, b: u32, allocated_ptr: i32) {
|
||||||
let a = Mark::from_u32(a);
|
let a = Mark::from_u32(a);
|
||||||
let b = Mark::from_u32(b);
|
let b = Mark::from_u32(b);
|
||||||
|
|
||||||
@ -70,7 +70,11 @@ pub fn syntax_context_apply_mark_proxy(self_syntax_context: u32, mark: u32) -> u
|
|||||||
.as_u32()
|
.as_u32()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn syntax_context_remove_mark_proxy(env: &HostEnvironment, self_mark: u32, allocated_ptr: i32) {
|
pub fn syntax_context_remove_mark_proxy(
|
||||||
|
env: &BaseHostEnvironment,
|
||||||
|
self_mark: u32,
|
||||||
|
allocated_ptr: i32,
|
||||||
|
) {
|
||||||
let mut self_mark = SyntaxContext::from_u32(self_mark);
|
let mut self_mark = SyntaxContext::from_u32(self_mark);
|
||||||
|
|
||||||
let return_value = self_mark.remove_mark();
|
let return_value = self_mark.remove_mark();
|
||||||
|
@ -46,7 +46,19 @@ use std::sync::Arc;
|
|||||||
use parking_lot::Mutex;
|
use parking_lot::Mutex;
|
||||||
use wasmer::{imports, Function, ImportObject, Module};
|
use wasmer::{imports, Function, ImportObject, Module};
|
||||||
|
|
||||||
use crate::{host_environment::HostEnvironment, imported_fn::comments::get_leading_comments_proxy};
|
use crate::{
|
||||||
|
host_environment::BaseHostEnvironment,
|
||||||
|
imported_fn::{
|
||||||
|
comments::{
|
||||||
|
add_leading_comment_proxy, add_leading_comments_proxy, add_pure_comment_proxy,
|
||||||
|
add_trailing_comment_proxy, add_trailing_comments_proxy, copy_comment_to_host_env,
|
||||||
|
get_leading_comments_proxy, get_trailing_comments_proxy, has_leading_comments_proxy,
|
||||||
|
has_trailing_comments_proxy, move_leading_comments_proxy, move_trailing_comments_proxy,
|
||||||
|
take_leading_comments_proxy, take_trailing_comments_proxy, CommentHostEnvironment,
|
||||||
|
},
|
||||||
|
set_transform_result::{set_transform_result, TransformResultHostEnvironment},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
mod comments;
|
mod comments;
|
||||||
mod handler;
|
mod handler;
|
||||||
@ -55,7 +67,6 @@ mod set_transform_result;
|
|||||||
|
|
||||||
use handler::*;
|
use handler::*;
|
||||||
use hygiene::*;
|
use hygiene::*;
|
||||||
use set_transform_result::*;
|
|
||||||
|
|
||||||
/// Create an ImportObject includes functions to be imported from host to the
|
/// Create an ImportObject includes functions to be imported from host to the
|
||||||
/// plugins.
|
/// plugins.
|
||||||
@ -68,16 +79,13 @@ pub(crate) fn build_import_object(
|
|||||||
// transfrom_result
|
// transfrom_result
|
||||||
let set_transform_result_fn_decl = Function::new_native_with_env(
|
let set_transform_result_fn_decl = Function::new_native_with_env(
|
||||||
wasmer_store,
|
wasmer_store,
|
||||||
HostEnvironment::new(transform_result),
|
TransformResultHostEnvironment::new(transform_result),
|
||||||
set_transform_result,
|
set_transform_result,
|
||||||
);
|
);
|
||||||
|
|
||||||
// handler
|
// handler
|
||||||
let emit_diagnostics_fn_decl = Function::new_native_with_env(
|
let emit_diagnostics_fn_decl =
|
||||||
wasmer_store,
|
Function::new_native_with_env(wasmer_store, BaseHostEnvironment::new(), emit_diagnostics);
|
||||||
HostEnvironment::new(transform_result),
|
|
||||||
emit_diagnostics,
|
|
||||||
);
|
|
||||||
|
|
||||||
// hygiene
|
// hygiene
|
||||||
let mark_fresh_fn_decl = Function::new_native(wasmer_store, mark_fresh_proxy);
|
let mark_fresh_fn_decl = Function::new_native(wasmer_store, mark_fresh_proxy);
|
||||||
@ -86,13 +94,13 @@ pub(crate) fn build_import_object(
|
|||||||
let mark_set_builtin_fn_decl = Function::new_native(wasmer_store, mark_set_builtin_proxy);
|
let mark_set_builtin_fn_decl = Function::new_native(wasmer_store, mark_set_builtin_proxy);
|
||||||
let mark_is_descendant_of_fn_decl = Function::new_native_with_env(
|
let mark_is_descendant_of_fn_decl = Function::new_native_with_env(
|
||||||
wasmer_store,
|
wasmer_store,
|
||||||
HostEnvironment::new(transform_result),
|
BaseHostEnvironment::new(),
|
||||||
mark_is_descendant_of_proxy,
|
mark_is_descendant_of_proxy,
|
||||||
);
|
);
|
||||||
|
|
||||||
let mark_least_ancestor_fn_decl = Function::new_native_with_env(
|
let mark_least_ancestor_fn_decl = Function::new_native_with_env(
|
||||||
wasmer_store,
|
wasmer_store,
|
||||||
HostEnvironment::new(transform_result),
|
BaseHostEnvironment::new(),
|
||||||
mark_least_ancestor_proxy,
|
mark_least_ancestor_proxy,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -100,19 +108,91 @@ pub(crate) fn build_import_object(
|
|||||||
Function::new_native(wasmer_store, syntax_context_apply_mark_proxy);
|
Function::new_native(wasmer_store, syntax_context_apply_mark_proxy);
|
||||||
let syntax_context_remove_mark_fn_decl = Function::new_native_with_env(
|
let syntax_context_remove_mark_fn_decl = Function::new_native_with_env(
|
||||||
wasmer_store,
|
wasmer_store,
|
||||||
HostEnvironment::new(transform_result),
|
BaseHostEnvironment::new(),
|
||||||
syntax_context_remove_mark_proxy,
|
syntax_context_remove_mark_proxy,
|
||||||
);
|
);
|
||||||
let syntax_context_outer_fn_decl =
|
let syntax_context_outer_fn_decl =
|
||||||
Function::new_native(wasmer_store, syntax_context_outer_proxy);
|
Function::new_native(wasmer_store, syntax_context_outer_proxy);
|
||||||
|
|
||||||
// comments
|
// comments
|
||||||
|
let comment_buffer = Arc::new(Mutex::new(vec![]));
|
||||||
|
|
||||||
|
let copy_comment_to_host_env_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
CommentHostEnvironment::new(&comment_buffer),
|
||||||
|
copy_comment_to_host_env,
|
||||||
|
);
|
||||||
|
|
||||||
|
let add_leading_comment_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
CommentHostEnvironment::new(&comment_buffer),
|
||||||
|
add_leading_comment_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let add_leading_comments_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
CommentHostEnvironment::new(&comment_buffer),
|
||||||
|
add_leading_comments_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let has_leading_comments_fn_decl =
|
||||||
|
Function::new_native(wasmer_store, has_leading_comments_proxy);
|
||||||
|
|
||||||
|
let move_leading_comments_fn_decl =
|
||||||
|
Function::new_native(wasmer_store, move_leading_comments_proxy);
|
||||||
|
|
||||||
|
let take_leading_comments_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
// take_* doesn't need to share buffer to pass values from plugin to the host - do not
|
||||||
|
// clone buffer here.
|
||||||
|
CommentHostEnvironment::new(&Default::default()),
|
||||||
|
take_leading_comments_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
let get_leading_comments_fn_decl = Function::new_native_with_env(
|
let get_leading_comments_fn_decl = Function::new_native_with_env(
|
||||||
wasmer_store,
|
wasmer_store,
|
||||||
HostEnvironment::new(transform_result),
|
// get_* doesn't need to share buffer to pass values from plugin to the host - do not clone
|
||||||
|
// buffer here.
|
||||||
|
CommentHostEnvironment::new(&Default::default()),
|
||||||
get_leading_comments_proxy,
|
get_leading_comments_proxy,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let add_trailing_comment_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
CommentHostEnvironment::new(&comment_buffer),
|
||||||
|
add_trailing_comment_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let add_trailing_comments_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
CommentHostEnvironment::new(&comment_buffer),
|
||||||
|
add_trailing_comments_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let has_trailing_comments_fn_decl =
|
||||||
|
Function::new_native(wasmer_store, has_trailing_comments_proxy);
|
||||||
|
|
||||||
|
let move_trailing_comments_fn_decl =
|
||||||
|
Function::new_native(wasmer_store, move_trailing_comments_proxy);
|
||||||
|
|
||||||
|
let take_trailing_comments_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
// take_* doesn't need to share buffer to pass values from plugin to the host - do not
|
||||||
|
// clone buffer here.
|
||||||
|
CommentHostEnvironment::new(&Default::default()),
|
||||||
|
take_trailing_comments_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let get_trailing_comments_fn_decl = Function::new_native_with_env(
|
||||||
|
wasmer_store,
|
||||||
|
// get_* doesn't need to share buffer to pass values from plugin to the host - do not clone
|
||||||
|
// buffer here.
|
||||||
|
CommentHostEnvironment::new(&Default::default()),
|
||||||
|
get_trailing_comments_proxy,
|
||||||
|
);
|
||||||
|
|
||||||
|
let add_pure_comment_fn_decl = Function::new_native(wasmer_store, add_pure_comment_proxy);
|
||||||
|
|
||||||
imports! {
|
imports! {
|
||||||
"env" => {
|
"env" => {
|
||||||
// transform
|
// transform
|
||||||
@ -130,7 +210,20 @@ pub(crate) fn build_import_object(
|
|||||||
"__syntax_context_remove_mark_proxy" => syntax_context_remove_mark_fn_decl,
|
"__syntax_context_remove_mark_proxy" => syntax_context_remove_mark_fn_decl,
|
||||||
"__syntax_context_outer_proxy" => syntax_context_outer_fn_decl,
|
"__syntax_context_outer_proxy" => syntax_context_outer_fn_decl,
|
||||||
// comments
|
// comments
|
||||||
|
"__copy_comment_to_host_env" => copy_comment_to_host_env_fn_decl,
|
||||||
|
"__add_leading_comment_proxy" => add_leading_comment_fn_decl,
|
||||||
|
"__add_leading_comments_proxy" => add_leading_comments_fn_decl,
|
||||||
|
"__has_leading_comments_proxy" => has_leading_comments_fn_decl,
|
||||||
|
"__move_leading_comments_proxy" => move_leading_comments_fn_decl,
|
||||||
|
"__take_leading_comments_proxy" => take_leading_comments_fn_decl,
|
||||||
"__get_leading_comments_proxy" => get_leading_comments_fn_decl,
|
"__get_leading_comments_proxy" => get_leading_comments_fn_decl,
|
||||||
|
"__add_trailing_comment_proxy" => add_trailing_comment_fn_decl,
|
||||||
|
"__add_trailing_comments_proxy" => add_trailing_comments_fn_decl,
|
||||||
|
"__has_trailing_comments_proxy" => has_trailing_comments_fn_decl,
|
||||||
|
"__move_trailing_comments_proxy" => move_trailing_comments_fn_decl,
|
||||||
|
"__take_trailing_comments_proxy" => take_trailing_comments_fn_decl,
|
||||||
|
"__get_trailing_comments_proxy" => get_trailing_comments_fn_decl,
|
||||||
|
"__add_pure_comment_proxy" => add_pure_comment_fn_decl,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,40 @@
|
|||||||
use crate::{host_environment::HostEnvironment, memory_interop::copy_bytes_into_host};
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use parking_lot::Mutex;
|
||||||
|
use wasmer::{LazyInit, Memory};
|
||||||
|
|
||||||
|
use crate::memory_interop::copy_bytes_into_host;
|
||||||
|
|
||||||
|
/// Environment states allow to return guest's transform result back to the
|
||||||
|
/// host, using a buffer `transform_result` attached to the environment.
|
||||||
|
///
|
||||||
|
/// When plugin performs its transform it'll fill in `transform_result` with
|
||||||
|
/// serialized result. Host will reconstruct AST from those value.
|
||||||
|
#[derive(wasmer::WasmerEnv, Clone)]
|
||||||
|
pub struct TransformResultHostEnvironment {
|
||||||
|
#[wasmer(export)]
|
||||||
|
pub memory: wasmer::LazyInit<Memory>,
|
||||||
|
pub transform_result: Arc<Mutex<Vec<u8>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TransformResultHostEnvironment {
|
||||||
|
pub fn new(transform_result: &Arc<Mutex<Vec<u8>>>) -> TransformResultHostEnvironment {
|
||||||
|
TransformResultHostEnvironment {
|
||||||
|
memory: LazyInit::default(),
|
||||||
|
transform_result: transform_result.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Set plugin's transformed result into host's enviroment.
|
/// Set plugin's transformed result into host's enviroment.
|
||||||
/// This is an `imported` fn - when we instantiate plugin module, we inject this
|
/// This is an `imported` fn - when we instantiate plugin module, we inject this
|
||||||
/// fn into pluging's export space. Once transform completes, plugin will call
|
/// fn into pluging's export space. Once transform completes, plugin will call
|
||||||
/// this to set its result back to host.
|
/// this to set its result back to host.
|
||||||
pub fn set_transform_result(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
pub fn set_transform_result(
|
||||||
|
env: &TransformResultHostEnvironment,
|
||||||
|
bytes_ptr: i32,
|
||||||
|
bytes_ptr_len: i32,
|
||||||
|
) {
|
||||||
if let Some(memory) = env.memory_ref() {
|
if let Some(memory) = env.memory_ref() {
|
||||||
(*env.transform_result.lock()) = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
(*env.transform_result.lock()) = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||||
}
|
}
|
||||||
|
21
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
21
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
@ -63,15 +63,6 @@ dependencies = [
|
|||||||
"scoped-tls",
|
"scoped-tls",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "better_scoped_tls"
|
|
||||||
version = "0.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "b73e8ecdec39e98aa3b19e8cd0b8ed8f77ccb86a6b0b2dc7cd86d105438a2123"
|
|
||||||
dependencies = [
|
|
||||||
"scoped-tls",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
@ -621,12 +612,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_common"
|
name = "swc_common"
|
||||||
version = "0.17.18"
|
version = "0.17.19"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"ahash",
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"ast_node",
|
"ast_node",
|
||||||
"better_scoped_tls 0.1.0",
|
"better_scoped_tls",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"debug_unreachable",
|
"debug_unreachable",
|
||||||
"either",
|
"either",
|
||||||
@ -647,7 +638,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_ecma_ast"
|
name = "swc_ecma_ast"
|
||||||
version = "0.73.0"
|
version = "0.73.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"is-macro",
|
"is-macro",
|
||||||
"num-bigint",
|
"num-bigint",
|
||||||
@ -701,7 +692,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_plugin"
|
name = "swc_plugin"
|
||||||
version = "0.39.0"
|
version = "0.41.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"swc_atoms",
|
"swc_atoms",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
@ -715,14 +706,14 @@ dependencies = [
|
|||||||
name = "swc_plugin_comments"
|
name = "swc_plugin_comments"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"better_scoped_tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"better_scoped_tls",
|
||||||
"rkyv",
|
"rkyv",
|
||||||
"swc_common",
|
"swc_common",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "swc_plugin_macro"
|
name = "swc_plugin_macro"
|
||||||
version = "0.3.1"
|
version = "0.4.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
Loading…
Reference in New Issue
Block a user