mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 13:51:19 +03:00
feat(plugin): Implement PoC of comments api (#4206)
This commit is contained in:
parent
be9017dfe1
commit
536a190dc9
1
.gitignore
vendored
1
.gitignore
vendored
@ -56,3 +56,4 @@ pkg/
|
||||
|
||||
*.mm_profdata
|
||||
.tsbuildinfo
|
||||
.swc/
|
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -2345,9 +2345,9 @@ checksum = "11000e6ba5020e53e7cc26f73b91ae7d5496b4977851479edb66b694c0675c21"
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.35"
|
||||
version = "0.7.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cdcf5caf69bcc87b1e3f5427b4f21a32fdd53c2847687bdf9861abb1cdaa0d8"
|
||||
checksum = "5230ae2981a885590b0dc84e0b24c0ed23ad24f7adc0eb824b26cafa961f7c36"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
"hashbrown 0.12.0",
|
||||
@ -2359,9 +2359,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.35"
|
||||
version = "0.7.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6cf557da1f81b8c7e889c59c9c3abaf6978f7feb156b9579e4f8bf6d7a2bada"
|
||||
checksum = "0fc752d5925dbcb324522f3a4c93193d17f107b2e11810913aa3ad352fa01480"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -2856,6 +2856,7 @@ dependencies = [
|
||||
"swc_error_reporters",
|
||||
"swc_node_base",
|
||||
"swc_node_comments",
|
||||
"swc_plugin_comments",
|
||||
"swc_plugin_runner",
|
||||
"swc_visit",
|
||||
"testing",
|
||||
@ -3774,9 +3775,19 @@ dependencies = [
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_quote",
|
||||
"swc_ecma_visit",
|
||||
"swc_plugin_comments",
|
||||
"swc_plugin_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin_comments"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"better_scoped_tls",
|
||||
"rkyv",
|
||||
"swc_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin_macro"
|
||||
version = "0.3.1"
|
||||
@ -3801,6 +3812,7 @@ dependencies = [
|
||||
"swc_ecma_loader",
|
||||
"swc_ecma_parser",
|
||||
"swc_ecma_visit",
|
||||
"swc_plugin_comments",
|
||||
"testing",
|
||||
"tracing",
|
||||
"wasmer",
|
||||
|
@ -14,6 +14,7 @@ members = [
|
||||
"crates/swc_plugin_macro",
|
||||
"crates/swc_plugin_runner",
|
||||
"crates/swc_plugin_testing",
|
||||
"crates/swc_plugin_comments",
|
||||
"crates/swc_timer",
|
||||
"crates/swc_webpack_ast",
|
||||
"crates/wasm",
|
||||
|
@ -27,7 +27,7 @@ concurrent = [
|
||||
]
|
||||
debug = ["swc_ecma_visit/debug"]
|
||||
node = ["napi", "napi-derive"]
|
||||
plugin = ["swc_plugin_runner"]
|
||||
plugin = ["swc_plugin_runner", "swc_plugin_comments/plugin-rt"]
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.7.4"
|
||||
@ -80,6 +80,7 @@ swc_ecmascript = { version = "0.140.0", path = "../swc_ecmascript" }
|
||||
swc_error_reporters = { version = "0.1.0", path = "../swc_error_reporters" }
|
||||
swc_node_comments = { version = "0.4.0", path = "../swc_node_comments" }
|
||||
swc_plugin_runner = { version = "0.48.0", path = "../swc_plugin_runner", optional = true, default-features = false }
|
||||
swc_plugin_comments = { version = "0.1.0", path = "../swc_plugin_comments", optional = true }
|
||||
swc_visit = { version = "0.3.0", path = "../swc_visit" }
|
||||
tracing = "0.1.32"
|
||||
|
||||
|
@ -466,7 +466,13 @@ impl Options {
|
||||
swc_plugin_runner::cache::init_plugin_module_cache_once(&experimental.cache_root);
|
||||
}
|
||||
|
||||
crate::plugin::plugins(Some(plugin_resolver), experimental, plugin_context)
|
||||
let comments = comments.cloned();
|
||||
crate::plugin::plugins(
|
||||
Some(plugin_resolver),
|
||||
comments,
|
||||
experimental,
|
||||
plugin_context,
|
||||
)
|
||||
};
|
||||
|
||||
// Native runtime plugin target, based on assumption we have
|
||||
@ -487,7 +493,8 @@ impl Options {
|
||||
};
|
||||
|
||||
swc_plugin_runner::cache::init_plugin_module_cache_once();
|
||||
crate::plugin::plugins(None, experimental, plugin_context)
|
||||
let comments = comments.cloned();
|
||||
crate::plugin::plugins(None, comments, experimental, plugin_context)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "plugin"))]
|
||||
|
@ -44,12 +44,14 @@ pub struct PluginContext {
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn plugins(
|
||||
resolver: Option<CachingResolver<NodeModulesResolver>>,
|
||||
comments: Option<swc_common::comments::SingleThreadedComments>,
|
||||
config: crate::config::JscExperimental,
|
||||
plugin_context: PluginContext,
|
||||
) -> impl Fold {
|
||||
{
|
||||
RustPlugins {
|
||||
resolver,
|
||||
comments,
|
||||
plugins: config.plugins,
|
||||
plugin_context,
|
||||
}
|
||||
@ -63,6 +65,7 @@ pub fn plugins() -> impl Fold {
|
||||
|
||||
struct RustPlugins {
|
||||
resolver: Option<CachingResolver<NodeModulesResolver>>,
|
||||
comments: Option<swc_common::comments::SingleThreadedComments>,
|
||||
plugins: Option<Vec<PluginConfig>>,
|
||||
plugin_context: PluginContext,
|
||||
}
|
||||
@ -77,65 +80,77 @@ impl RustPlugins {
|
||||
use swc_common::{plugin::Serialized, FileName};
|
||||
use swc_ecma_loader::resolve::Resolve;
|
||||
|
||||
let mut serialized = Serialized::serialize(&n)?;
|
||||
// swc_plugin_macro will not inject proxy to the comments if comments is empty
|
||||
let should_enable_comments_proxy = self.comments.is_some();
|
||||
|
||||
// Run plugin transformation against current program.
|
||||
// We do not serialize / deserialize between each plugin execution but
|
||||
// copies raw transformed bytes directly into plugin's memory space.
|
||||
// Note: This doesn't mean plugin won't perform any se/deserialization: it
|
||||
// still have to construct from raw bytes internally to perform actual
|
||||
// transform.
|
||||
if let Some(plugins) = &self.plugins {
|
||||
for p in plugins {
|
||||
let span = tracing::span!(
|
||||
tracing::Level::INFO,
|
||||
"serialize_context",
|
||||
plugin_module = p.0.as_str()
|
||||
);
|
||||
let context_span_guard = span.enter();
|
||||
// Set comments once per whole plugin transform execution.
|
||||
swc_plugin_comments::COMMENTS.set(
|
||||
&swc_plugin_comments::HostCommentsStorage {
|
||||
inner: self.comments.clone(),
|
||||
},
|
||||
|| {
|
||||
let mut serialized = Serialized::serialize(&n)?;
|
||||
|
||||
let config_json = serde_json::to_string(&p.1)
|
||||
.context("Failed to serialize plugin config as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
// Run plugin transformation against current program.
|
||||
// We do not serialize / deserialize between each plugin execution but
|
||||
// copies raw transformed bytes directly into plugin's memory space.
|
||||
// Note: This doesn't mean plugin won't perform any se/deserialization: it
|
||||
// still have to construct from raw bytes internally to perform actual
|
||||
// transform.
|
||||
if let Some(plugins) = &self.plugins {
|
||||
for p in plugins {
|
||||
let span = tracing::span!(
|
||||
tracing::Level::INFO,
|
||||
"serialize_context",
|
||||
plugin_module = p.0.as_str()
|
||||
);
|
||||
let context_span_guard = span.enter();
|
||||
|
||||
let context_json = serde_json::to_string(&self.plugin_context)
|
||||
.context("Failed to serialize plugin context as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
let config_json = serde_json::to_string(&p.1)
|
||||
.context("Failed to serialize plugin config as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
|
||||
let resolved_path = self
|
||||
.resolver
|
||||
.as_ref()
|
||||
.expect("filesystem_cache should provide resolver")
|
||||
.resolve(&FileName::Real(PathBuf::from(&p.0)), &p.0)?;
|
||||
let context_json = serde_json::to_string(&self.plugin_context)
|
||||
.context("Failed to serialize plugin context as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
|
||||
let path = if let FileName::Real(value) = resolved_path {
|
||||
Arc::new(value)
|
||||
} else {
|
||||
anyhow::bail!("Failed to resolve plugin path: {:?}", resolved_path);
|
||||
};
|
||||
drop(context_span_guard);
|
||||
let resolved_path = self
|
||||
.resolver
|
||||
.as_ref()
|
||||
.expect("filesystem_cache should provide resolver")
|
||||
.resolve(&FileName::Real(PathBuf::from(&p.0)), &p.0)?;
|
||||
|
||||
let span = tracing::span!(
|
||||
tracing::Level::INFO,
|
||||
"execute_plugin_runner",
|
||||
plugin_module = p.0.as_str()
|
||||
);
|
||||
let transform_span_guard = span.enter();
|
||||
serialized = swc_plugin_runner::apply_transform_plugin(
|
||||
&p.0,
|
||||
&path,
|
||||
&swc_plugin_runner::cache::PLUGIN_MODULE_CACHE,
|
||||
serialized,
|
||||
config_json,
|
||||
context_json,
|
||||
)?;
|
||||
drop(transform_span_guard);
|
||||
}
|
||||
}
|
||||
let path = if let FileName::Real(value) = resolved_path {
|
||||
Arc::new(value)
|
||||
} else {
|
||||
anyhow::bail!("Failed to resolve plugin path: {:?}", resolved_path);
|
||||
};
|
||||
drop(context_span_guard);
|
||||
|
||||
// Plugin transformation is done. Deserialize transformed bytes back
|
||||
// into Program
|
||||
Serialized::deserialize(&serialized)
|
||||
let span = tracing::span!(
|
||||
tracing::Level::INFO,
|
||||
"execute_plugin_runner",
|
||||
plugin_module = p.0.as_str()
|
||||
);
|
||||
let transform_span_guard = span.enter();
|
||||
serialized = swc_plugin_runner::apply_transform_plugin(
|
||||
&p.0,
|
||||
&path,
|
||||
&swc_plugin_runner::cache::PLUGIN_MODULE_CACHE,
|
||||
serialized,
|
||||
config_json,
|
||||
context_json,
|
||||
should_enable_comments_proxy,
|
||||
)?;
|
||||
drop(transform_span_guard);
|
||||
}
|
||||
}
|
||||
|
||||
// Plugin transformation is done. Deserialize transformed bytes back
|
||||
// into Program
|
||||
Serialized::deserialize(&serialized)
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "plugin", target_arch = "wasm32"))]
|
||||
@ -146,30 +161,40 @@ impl RustPlugins {
|
||||
use swc_common::{plugin::Serialized, FileName};
|
||||
use swc_ecma_loader::resolve::Resolve;
|
||||
|
||||
let mut serialized = Serialized::serialize(&n)?;
|
||||
let should_enable_comments_proxy = self.comments.is_some();
|
||||
|
||||
if let Some(plugins) = &self.plugins {
|
||||
for p in plugins {
|
||||
let config_json = serde_json::to_string(&p.1)
|
||||
.context("Failed to serialize plugin config as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
swc_plugin_comments::COMMENTS.set(
|
||||
&swc_plugin_comments::HostCommentsStorage {
|
||||
inner: self.comments.clone(),
|
||||
},
|
||||
|| {
|
||||
let mut serialized = Serialized::serialize(&n)?;
|
||||
|
||||
let context_json = serde_json::to_string(&self.plugin_context)
|
||||
.context("Failed to serialize plugin context as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
if let Some(plugins) = &self.plugins {
|
||||
for p in plugins {
|
||||
let config_json = serde_json::to_string(&p.1)
|
||||
.context("Failed to serialize plugin config as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
|
||||
serialized = swc_plugin_runner::apply_transform_plugin(
|
||||
&p.0,
|
||||
&PathBuf::from(&p.0),
|
||||
&swc_plugin_runner::cache::PLUGIN_MODULE_CACHE,
|
||||
serialized,
|
||||
config_json,
|
||||
context_json,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
let context_json = serde_json::to_string(&self.plugin_context)
|
||||
.context("Failed to serialize plugin context as json")
|
||||
.and_then(|value| Serialized::serialize(&value))?;
|
||||
|
||||
Serialized::deserialize(&serialized)
|
||||
serialized = swc_plugin_runner::apply_transform_plugin(
|
||||
&p.0,
|
||||
&PathBuf::from(&p.0),
|
||||
&swc_plugin_runner::cache::PLUGIN_MODULE_CACHE,
|
||||
serialized,
|
||||
config_json,
|
||||
context_json,
|
||||
should_enable_comments_proxy,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Serialized::deserialize(&serialized)
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -537,6 +537,10 @@ impl SingleThreadedComments {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(
|
||||
feature = "rkyv",
|
||||
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
|
||||
)]
|
||||
pub struct Comment {
|
||||
pub kind: CommentKind,
|
||||
pub span: Span,
|
||||
@ -550,6 +554,10 @@ impl Spanned for Comment {
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[cfg_attr(
|
||||
feature = "rkyv",
|
||||
derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)
|
||||
)]
|
||||
pub enum CommentKind {
|
||||
Line,
|
||||
Block,
|
||||
|
@ -27,7 +27,7 @@ pub enum PluginError {
|
||||
/// plugin_macro, noramlly plugin author should not raise this manually.
|
||||
SizeInteropFailure(String),
|
||||
/// Occurs when failed to reconstruct a struct from `Serialized`.
|
||||
Deserialize((String, Vec<u8>)),
|
||||
Deserialize(String),
|
||||
/// Occurs when failed to serialize a struct into `Serialized`.
|
||||
/// Unlike deserialize error, this error cannot forward any context for the
|
||||
/// raw bytes: when serialze failed, there's nothing we can pass between
|
||||
@ -94,4 +94,27 @@ impl Serialized {
|
||||
.deserialize(&mut rkyv::Infallible)
|
||||
.with_context(|| format!("failed to deserialize `{}`", type_name::<W>()))
|
||||
}
|
||||
|
||||
/// Convinient wrapper to Serialized::* to construct actual struct from raw
|
||||
/// ptr. This is common workflow on both of runtime (host / plugin) to
|
||||
/// deserialize struct from allocated / copied ptr.
|
||||
///
|
||||
/// # Safety
|
||||
/// This is naturally unsafe by constructing bytes slice from raw ptr.
|
||||
pub unsafe fn deserialize_from_ptr<W>(
|
||||
raw_allocated_ptr: *const u8,
|
||||
raw_allocated_ptr_len: i32,
|
||||
) -> Result<W, Error>
|
||||
where
|
||||
W: rkyv::Archive,
|
||||
W::Archived: rkyv::Deserialize<W, rkyv::Infallible>,
|
||||
{
|
||||
// Create serialized bytes slice from ptr
|
||||
let raw_ptr_bytes = unsafe {
|
||||
std::slice::from_raw_parts(raw_allocated_ptr, raw_allocated_ptr_len.try_into()?)
|
||||
};
|
||||
|
||||
let serialized = Serialized::new_for_plugin(raw_ptr_bytes, raw_allocated_ptr_len);
|
||||
Serialized::deserialize(&serialized)
|
||||
}
|
||||
}
|
||||
|
@ -91,9 +91,6 @@ extern "C" {
|
||||
fn __mark_is_descendant_of_proxy(self_mark: u32, ancestor: u32, allocated_ptr: i32);
|
||||
fn __mark_least_ancestor(a: u32, b: u32, allocated_ptr: i32);
|
||||
fn __syntax_context_remove_mark_proxy(self_mark: u32, allocated_ptr: i32);
|
||||
|
||||
fn __alloc(size: usize) -> *mut u8;
|
||||
fn __free(ptr: *mut u8, size: usize) -> i32;
|
||||
}
|
||||
|
||||
impl Mark {
|
||||
@ -176,8 +173,9 @@ impl Mark {
|
||||
// In here, preallocate memory for the context.
|
||||
let serialized = crate::plugin::Serialized::serialize(&MutableMarkContext(0, 0, 0))
|
||||
.expect("Should be serializable");
|
||||
let len = serialized.as_ref().len();
|
||||
let ptr = unsafe { __alloc(len) };
|
||||
let serialized_ref = serialized.as_ref();
|
||||
let ptr = serialized_ref.as_ptr();
|
||||
let len = serialized_ref.len();
|
||||
|
||||
// Calling host proxy fn. Inside of host proxy, host will
|
||||
// write the result into allocated context in the guest memory space.
|
||||
@ -186,18 +184,15 @@ impl Mark {
|
||||
}
|
||||
|
||||
// Deserialize result, assign / return values as needed.
|
||||
let raw_result_bytes = unsafe { std::slice::from_raw_parts(ptr, len) };
|
||||
let result =
|
||||
crate::plugin::Serialized::new_for_plugin(raw_result_bytes, len.try_into().expect(""));
|
||||
let context: MutableMarkContext =
|
||||
crate::plugin::Serialized::deserialize(&result).expect("Should be deserializable");
|
||||
|
||||
let context: MutableMarkContext = unsafe {
|
||||
crate::plugin::Serialized::deserialize_from_ptr(
|
||||
ptr,
|
||||
len.try_into().expect("Should able to convert ptr length"),
|
||||
)
|
||||
.expect("Should able to deserialize")
|
||||
};
|
||||
self = Mark::from_u32(context.0);
|
||||
|
||||
unsafe {
|
||||
__free(ptr, len);
|
||||
}
|
||||
|
||||
return context.2 != 0;
|
||||
}
|
||||
|
||||
@ -219,26 +214,24 @@ impl Mark {
|
||||
pub fn least_ancestor(mut a: Mark, mut b: Mark) -> Mark {
|
||||
let serialized = crate::plugin::Serialized::serialize(&MutableMarkContext(0, 0, 0))
|
||||
.expect("Should be serializable");
|
||||
let len = serialized.as_ref().len();
|
||||
let ptr = unsafe { __alloc(len) };
|
||||
let serialized_ref = serialized.as_ref();
|
||||
let ptr = serialized_ref.as_ptr();
|
||||
let len = serialized_ref.len();
|
||||
|
||||
unsafe {
|
||||
__mark_least_ancestor(a.0, b.0, ptr as _);
|
||||
}
|
||||
|
||||
let raw_result_bytes = unsafe { std::slice::from_raw_parts(ptr, len) };
|
||||
let result =
|
||||
crate::plugin::Serialized::new_for_plugin(raw_result_bytes, len.try_into().expect(""));
|
||||
let context: MutableMarkContext =
|
||||
crate::plugin::Serialized::deserialize(&result).expect("Should be deserializable");
|
||||
|
||||
let context: MutableMarkContext = unsafe {
|
||||
crate::plugin::Serialized::deserialize_from_ptr(
|
||||
ptr,
|
||||
len.try_into().expect("Should able to convert ptr length"),
|
||||
)
|
||||
.expect("Should able to deserialize")
|
||||
};
|
||||
a = Mark::from_u32(context.0);
|
||||
b = Mark::from_u32(context.1);
|
||||
|
||||
unsafe {
|
||||
__free(ptr, len);
|
||||
}
|
||||
|
||||
return Mark(context.2);
|
||||
}
|
||||
|
||||
@ -387,25 +380,24 @@ impl SyntaxContext {
|
||||
let context = MutableMarkContext(0, 0, 0);
|
||||
let serialized =
|
||||
crate::plugin::Serialized::serialize(&context).expect("Should be serializable");
|
||||
let len = serialized.as_ref().len();
|
||||
let ptr = unsafe { __alloc(len) };
|
||||
let serialized_ref = serialized.as_ref();
|
||||
let ptr = serialized_ref.as_ptr();
|
||||
let len = serialized_ref.len();
|
||||
|
||||
unsafe {
|
||||
__syntax_context_remove_mark_proxy(self.0, ptr as _);
|
||||
}
|
||||
|
||||
let raw_result_bytes = unsafe { std::slice::from_raw_parts(ptr, len) };
|
||||
let result =
|
||||
crate::plugin::Serialized::new_for_plugin(raw_result_bytes, len.try_into().expect(""));
|
||||
let context: MutableMarkContext =
|
||||
crate::plugin::Serialized::deserialize(&result).expect("Should be deserializable");
|
||||
let context: MutableMarkContext = unsafe {
|
||||
crate::plugin::Serialized::deserialize_from_ptr(
|
||||
ptr,
|
||||
len.try_into().expect("Should able to convert ptr length"),
|
||||
)
|
||||
.expect("Should able to deserialize")
|
||||
};
|
||||
|
||||
*self = SyntaxContext(context.0);
|
||||
|
||||
unsafe {
|
||||
__free(ptr, len);
|
||||
}
|
||||
|
||||
return Mark::from_u32(context.2);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,9 @@ swc_atoms = { version = "0.2.0", path = "../swc_atoms" }
|
||||
swc_common = { version = "0.17.0", path = "../swc_common", features = [
|
||||
"plugin-mode",
|
||||
] }
|
||||
swc_plugin_comments = { version = "0.1.0", path = "../swc_plugin_comments", features = [
|
||||
"plugin-mode",
|
||||
] }
|
||||
swc_ecma_ast = { version = "0.73.0", path = "../swc_ecma_ast", features = [
|
||||
"rkyv-impl",
|
||||
] }
|
||||
|
@ -1,31 +0,0 @@
|
||||
use swc_common::plugin::Serialized;
|
||||
|
||||
#[cfg(target_arch = "wasm32")] // Allow testing
|
||||
extern "C" {
|
||||
fn __emit_diagnostics(bytes_ptr: i32, bytes_ptr_len: i32);
|
||||
fn __free(bytes_ptr: i32, size: i32) -> i32;
|
||||
}
|
||||
|
||||
/// An emitter for the Diagnostic in plugin's context by borrowing host's
|
||||
/// environment context.
|
||||
///
|
||||
/// It is not expected to call this directly inside of plugin transform.
|
||||
/// Instead, it is encouraged to use global HANDLER.
|
||||
pub struct PluginDiagnosticsEmitter {}
|
||||
|
||||
impl swc_common::errors::Emitter for PluginDiagnosticsEmitter {
|
||||
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
|
||||
fn emit(&mut self, db: &swc_common::errors::DiagnosticBuilder<'_>) {
|
||||
let diag =
|
||||
Serialized::serialize(&*db.diagnostic).expect("Should able to serialize Diagnostic");
|
||||
let diag_ref = diag.as_ref();
|
||||
|
||||
let ptr = diag_ref.as_ptr() as i32;
|
||||
let len = diag_ref.len() as i32;
|
||||
|
||||
#[cfg(target_arch = "wasm32")] // Allow testing
|
||||
unsafe {
|
||||
__emit_diagnostics(ptr, len);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,34 +1,37 @@
|
||||
use swc_common::sync::OnceCell;
|
||||
use swc_common::{plugin::Serialized, sync::OnceCell};
|
||||
|
||||
/// Simple substitution for scoped_thread_local with limited interface parity.
|
||||
/// The only available fn in this struct is `with`, which is being used for the
|
||||
/// consumers when they need to access global scope handler (HANDLER.with()).
|
||||
/// Any other interfaces to support thread local is not available.
|
||||
pub struct PseudoScopedKey {
|
||||
// As we can't use scoped_thread_local for the global HANDLER, it is challenging
|
||||
// to set its inner handler for each plugin scope's diagnostic emitter.
|
||||
// Via lazy init OnceCell we keep static HANDLER as immutable, also allows to set
|
||||
// plugin specific values when proc_macro expands plugin's transform helper.
|
||||
pub inner: OnceCell<swc_common::errors::Handler>,
|
||||
use crate::pseudo_scoped_key::PseudoScopedKey;
|
||||
|
||||
#[cfg(target_arch = "wasm32")] // Allow testing
|
||||
extern "C" {
|
||||
fn __emit_diagnostics(bytes_ptr: i32, bytes_ptr_len: i32);
|
||||
fn __free(bytes_ptr: i32, size: i32) -> i32;
|
||||
}
|
||||
|
||||
impl PseudoScopedKey {
|
||||
pub fn with<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&swc_common::errors::Handler) -> R,
|
||||
{
|
||||
f(self.inner.get().expect("Should set handler before call"))
|
||||
/// An emitter for the Diagnostic in plugin's context by borrowing host's
|
||||
/// environment context.
|
||||
///
|
||||
/// It is not expected to call this directly inside of plugin transform.
|
||||
/// Instead, it is encouraged to use global HANDLER.
|
||||
pub struct PluginDiagnosticsEmitter;
|
||||
|
||||
impl swc_common::errors::Emitter for PluginDiagnosticsEmitter {
|
||||
#[cfg_attr(not(target_arch = "wasm32"), allow(unused))]
|
||||
fn emit(&mut self, db: &swc_common::errors::DiagnosticBuilder<'_>) {
|
||||
let diag =
|
||||
Serialized::serialize(&*db.diagnostic).expect("Should able to serialize Diagnostic");
|
||||
let diag_ref = diag.as_ref();
|
||||
|
||||
let ptr = diag_ref.as_ptr() as i32;
|
||||
let len = diag_ref.len() as i32;
|
||||
|
||||
#[cfg(target_arch = "wasm32")] // Allow testing
|
||||
unsafe {
|
||||
__emit_diagnostics(ptr, len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// This is to conform some of swc_common::errors::Handler's thread-safety
|
||||
// required properties.
|
||||
//
|
||||
// NOTE: This only works cause we know each plugin transform doesn't need any
|
||||
// thread safety. However, if wasm gets thread support and if we're going to
|
||||
// support it this should be revisited.
|
||||
unsafe impl std::marker::Sync for PseudoScopedKey {}
|
||||
|
||||
/// global context HANDLER in plugin's transform function.
|
||||
pub static HANDLER: PseudoScopedKey = PseudoScopedKey {
|
||||
inner: OnceCell::new(),
|
||||
|
@ -6,6 +6,11 @@ pub use swc_common::{
|
||||
plugin::{PluginError, Serialized},
|
||||
};
|
||||
|
||||
pub mod comments {
|
||||
pub use swc_common::comments::Comments;
|
||||
pub use swc_plugin_comments::PluginCommentsProxy;
|
||||
}
|
||||
|
||||
pub mod util {
|
||||
pub use swc_common::util::take;
|
||||
#[cfg(feature = "swc_ecma_quote")]
|
||||
@ -30,10 +35,10 @@ pub mod errors {
|
||||
pub use crate::handler::HANDLER;
|
||||
}
|
||||
|
||||
mod context;
|
||||
pub mod environment {
|
||||
pub use crate::context::*;
|
||||
pub use crate::handler::*;
|
||||
}
|
||||
use swc_plugin_comments::PluginCommentsProxy;
|
||||
// We don't set target cfg as it'll block macro expansions
|
||||
// in ide (i.e rust-analyzer) or non-wasm target `cargo check`
|
||||
pub use swc_plugin_macro::plugin_transform;
|
||||
@ -43,3 +48,24 @@ mod allocation;
|
||||
pub mod memory {
|
||||
pub use crate::allocation::*;
|
||||
}
|
||||
mod pseudo_scoped_key;
|
||||
|
||||
/// An arbitary metadata for given Program to run transform in plugin.
|
||||
/// These are information not directly attached to Program's AST structures
|
||||
/// but required for certain transforms.
|
||||
#[derive(Debug)]
|
||||
pub struct TransformPluginProgramMetadata {
|
||||
/// Proxy to the comments for the Program passed into plugin.
|
||||
/// This is a proxy to the actual data lives in the host. Only when plugin
|
||||
/// attempts to read these it'll ask to the host to get values.
|
||||
pub comments: Option<PluginCommentsProxy>,
|
||||
/// Stringified JSON value for given plugin's configuration.
|
||||
/// This is readonly. Changing value in plugin doesn't affect host's
|
||||
/// behavior.
|
||||
pub plugin_config: String,
|
||||
/// Stringified JSON value for relative context while running transform,
|
||||
/// like filenames.
|
||||
/// /// This is readonly. Changing value in plugin doesn't affect host's
|
||||
/// behavior.
|
||||
pub transform_context: String,
|
||||
}
|
||||
|
28
crates/swc_plugin/src/pseudo_scoped_key.rs
Normal file
28
crates/swc_plugin/src/pseudo_scoped_key.rs
Normal file
@ -0,0 +1,28 @@
|
||||
/// Simple substitution for scoped_thread_local with limited interface parity.
|
||||
/// The only available fn in this struct is `with`, which is being used for the
|
||||
/// consumers when they need to access global scope handler (HANDLER.with()).
|
||||
/// Any other interfaces to support thread local is not available.
|
||||
pub struct PseudoScopedKey {
|
||||
// As we can't use scoped_thread_local for the global HANDLER, it is challenging
|
||||
// to set its inner handler for each plugin scope's diagnostic emitter.
|
||||
// Via lazy init OnceCell we keep static HANDLER as immutable, also allows to set
|
||||
// plugin specific values when proc_macro expands plugin's transform helper.
|
||||
pub inner: swc_common::sync::OnceCell<swc_common::errors::Handler>,
|
||||
}
|
||||
|
||||
impl PseudoScopedKey {
|
||||
pub fn with<F, R>(&self, f: F) -> R
|
||||
where
|
||||
F: FnOnce(&swc_common::errors::Handler) -> R,
|
||||
{
|
||||
f(self.inner.get().expect("Should set handler before call"))
|
||||
}
|
||||
}
|
||||
|
||||
// This is to conform some of swc_common::errors::Handler's thread-safety
|
||||
// required properties.
|
||||
//
|
||||
// NOTE: This only works cause we know each plugin transform doesn't need any
|
||||
// thread safety. However, if wasm gets thread support and if we're going to
|
||||
// support it this should be revisited.
|
||||
unsafe impl std::marker::Sync for PseudoScopedKey {}
|
22
crates/swc_plugin_comments/Cargo.toml
Normal file
22
crates/swc_plugin_comments/Cargo.toml
Normal file
@ -0,0 +1,22 @@
|
||||
[package]
|
||||
authors = ["강동윤 <kdy1997.dev@gmail.com>", "OJ Kwon <kwon.ohjoong@gmail.com>"]
|
||||
description = "Internal sharable storage for the comments between host to the plugin"
|
||||
name = "swc_plugin_comments"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
repository = "https://github.com/swc-project/swc.git"
|
||||
|
||||
[features]
|
||||
# swc/core, which runs plugin
|
||||
plugin-rt = []
|
||||
# actual wasm plugin binary
|
||||
plugin-mode = []
|
||||
|
||||
|
||||
[dependencies]
|
||||
better_scoped_tls = { version = "0.1.0", path = "../better_scoped_tls" }
|
||||
rkyv = "0.7.36"
|
||||
swc_common = { version = "0.17.0", path = "../swc_common", features = [
|
||||
"plugin-base",
|
||||
] }
|
21
crates/swc_plugin_comments/src/host_comments_storage.rs
Normal file
21
crates/swc_plugin_comments/src/host_comments_storage.rs
Normal file
@ -0,0 +1,21 @@
|
||||
/// A struct to internally store current file's comments for the
|
||||
/// transform plugins.
|
||||
///
|
||||
/// This storage is introduced to conform with existing design to the comments,
|
||||
/// specifically `SingleThreadedComments`. It doesn't support thread-safety
|
||||
/// which does not allow to be passed into wasmerEnv (HostEnvironment). A scoped
|
||||
/// tls holds inner comments as global, per each transform execution. Refer
|
||||
/// `swc::RustPlugins::apply_transform_plugin` for the responsibility to manage
|
||||
/// actual data.
|
||||
///
|
||||
/// Should never attempt to use this other than plugin_runner.
|
||||
// TODO: This storage does not support mutable yet
|
||||
#[cfg(feature = "plugin-rt")]
|
||||
pub struct HostCommentsStorage {
|
||||
pub inner: Option<swc_common::comments::SingleThreadedComments>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "plugin-rt")]
|
||||
better_scoped_tls::scoped_tls!(
|
||||
pub static COMMENTS: HostCommentsStorage
|
||||
);
|
8
crates/swc_plugin_comments/src/lib.rs
Normal file
8
crates/swc_plugin_comments/src/lib.rs
Normal file
@ -0,0 +1,8 @@
|
||||
mod host_comments_storage;
|
||||
#[cfg(feature = "plugin-rt")]
|
||||
pub use host_comments_storage::{HostCommentsStorage, COMMENTS};
|
||||
|
||||
mod plugin_comments_proxy;
|
||||
pub use plugin_comments_proxy::CommentsVecPtr;
|
||||
#[cfg(feature = "plugin-mode")]
|
||||
pub use plugin_comments_proxy::PluginCommentsProxy;
|
134
crates/swc_plugin_comments/src/plugin_comments_proxy.rs
Normal file
134
crates/swc_plugin_comments/src/plugin_comments_proxy.rs
Normal file
@ -0,0 +1,134 @@
|
||||
#[cfg(feature = "plugin-mode")]
|
||||
use swc_common::plugin::Serialized;
|
||||
#[cfg(feature = "plugin-mode")]
|
||||
use swc_common::{
|
||||
comments::{Comment, Comments},
|
||||
BytePos,
|
||||
};
|
||||
|
||||
#[cfg(target = "wasm32")]
|
||||
extern "C" {
|
||||
fn __get_leading_comments_proxy(byte_pos: u32, allocated_ret_ptr: i32) -> i32;
|
||||
}
|
||||
|
||||
/// A struct to exchance allocated Vec<Comment> between memory spaces.
|
||||
#[derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize)]
|
||||
pub struct CommentsVecPtr(pub i32, pub i32);
|
||||
|
||||
/// A struct implements `swc_common::comments::Comments` for the plugin.
|
||||
/// This is a proxy to the host's comments reference while plugin transform
|
||||
/// runs, does not contain actual data but lazily requests to the host for each
|
||||
/// interfaces.
|
||||
///
|
||||
/// This _does not_ derives serialization / deserialization for the
|
||||
/// Serialized::de/serialize interface. Instead, swc_plugin_macro injects an
|
||||
/// instance in plugin's runtime directly.
|
||||
#[cfg(feature = "plugin-mode")]
|
||||
#[derive(Debug)]
|
||||
pub struct PluginCommentsProxy;
|
||||
|
||||
#[cfg(feature = "plugin-mode")]
|
||||
impl Comments for PluginCommentsProxy {
|
||||
fn add_leading(&self, pos: BytePos, cmt: Comment) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn add_leading_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn has_leading(&self, pos: BytePos) -> bool {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
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
|
||||
let comments_vec_ptr = CommentsVecPtr(0, 0);
|
||||
let serialized_comments_vec_ptr = Serialized::serialize(&comments_vec_ptr)
|
||||
.expect("Should able to serialize CommentsVecPtr");
|
||||
let serialized_comments_vec_ptr_ref = serialized_comments_vec_ptr.as_ref();
|
||||
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();
|
||||
|
||||
#[cfg(target = "wasm32")]
|
||||
{
|
||||
let ret = unsafe {
|
||||
__get_leading_comments_proxy(pos.0, serialized_comments_vec_ptr_raw_ptr as _)
|
||||
};
|
||||
|
||||
if ret == 0 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
// First, reconstruct CommentsVecPtr to reveal ptr to the allocated
|
||||
// Vec<Comments>
|
||||
let comments_vec_ptr: CommentsVecPtr = unsafe {
|
||||
Serialized::deserialize_from_ptr(
|
||||
serialized_comments_vec_ptr_raw_ptr,
|
||||
serialized_comments_vec_ptr_raw_len
|
||||
.try_into()
|
||||
.expect("Should able to convert ptr length"),
|
||||
)
|
||||
.expect("Should able to deserialize CommentsVecPtr")
|
||||
};
|
||||
|
||||
// Using CommentsVecPtr's value, reconstruct actual Vec<Comments>
|
||||
Some(unsafe {
|
||||
Serialized::deserialize_from_ptr(comments_vec_ptr.0 as _, comments_vec_ptr.1)
|
||||
.expect("Returned comments should be serializable")
|
||||
})
|
||||
}
|
||||
|
||||
fn add_trailing(&self, pos: BytePos, cmt: Comment) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn add_trailing_comments(&self, pos: BytePos, comments: Vec<Comment>) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn has_trailing(&self, pos: BytePos) -> bool {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn move_trailing(&self, from: BytePos, to: BytePos) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn take_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn get_trailing(&self, pos: BytePos) -> Option<Vec<Comment>> {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn add_pure_comment(&self, pos: BytePos) {
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn with_leading<F, Ret>(&self, pos: BytePos, f: F) -> Ret
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(&[Comment]) -> Ret,
|
||||
{
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
|
||||
fn with_trailing<F, Ret>(&self, pos: BytePos, f: F) -> Ret
|
||||
where
|
||||
Self: Sized,
|
||||
F: FnOnce(&[Comment]) -> Ret,
|
||||
{
|
||||
unimplemented!("not implemented yet");
|
||||
}
|
||||
}
|
@ -58,68 +58,28 @@ fn handle_func(func: ItemFn) -> TokenStream {
|
||||
// There are some cases error won't be wrapped up however - for example, we expect
|
||||
// serialization of PluginError itself should succeed.
|
||||
#[no_mangle]
|
||||
pub fn #process_impl_ident(ast_ptr: *const u8, ast_ptr_len: i32, config_str_ptr: *const u8, config_str_ptr_len: i32, context_str_ptr: *const u8, context_str_ptr_len: i32) -> i32 {
|
||||
let ast_ptr_len_usize: Result<usize, std::num::TryFromIntError> = std::convert::TryInto::try_into(ast_ptr_len);
|
||||
let config_str_ptr_len_usize: Result<usize, std::num::TryFromIntError> = std::convert::TryInto::try_into(config_str_ptr_len);
|
||||
let context_str_ptr_len_usize: Result<usize, std::num::TryFromIntError> = std::convert::TryInto::try_into(context_str_ptr_len);
|
||||
|
||||
if ast_ptr_len_usize.is_err() {
|
||||
let err = swc_plugin::PluginError::SizeInteropFailure("Failed to convert size of AST pointer".to_string());
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
|
||||
if config_str_ptr_len_usize.is_err() {
|
||||
let err = swc_plugin::PluginError::SizeInteropFailure("Failed to convert size of plugin config string pointer".to_string());
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
|
||||
if context_str_ptr_len_usize.is_err() {
|
||||
let err = swc_plugin::PluginError::SizeInteropFailure("Failed to convert size of context string pointer".to_string());
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
|
||||
// Read raw serialized bytes from wasm's memory space. Host (SWC) should
|
||||
// allocate memory, copy bytes and pass ptr to plugin.
|
||||
let raw_ast_serialized_bytes =
|
||||
unsafe { std::slice::from_raw_parts(ast_ptr, ast_ptr_len_usize.unwrap()) };
|
||||
let raw_config_serialized_bytes =
|
||||
unsafe { std::slice::from_raw_parts(config_str_ptr, config_str_ptr_len_usize.unwrap()) };
|
||||
let raw_context_serialized_bytes =
|
||||
unsafe { std::slice::from_raw_parts(context_str_ptr, context_str_ptr_len_usize.unwrap()) };
|
||||
|
||||
// Reconstruct SerializedProgram from raw bytes
|
||||
let serialized_program = swc_plugin::Serialized::new_for_plugin(raw_ast_serialized_bytes, ast_ptr_len);
|
||||
let serialized_config = swc_plugin::Serialized::new_for_plugin(raw_config_serialized_bytes, config_str_ptr_len);
|
||||
let serialized_context = swc_plugin::Serialized::new_for_plugin(raw_context_serialized_bytes, context_str_ptr_len);
|
||||
|
||||
pub fn #process_impl_ident(ast_ptr: *const u8, ast_ptr_len: i32, config_str_ptr: *const u8, config_str_ptr_len: i32, context_str_ptr: *const u8, context_str_ptr_len: i32, should_enable_comments_proxy: i32) -> i32 {
|
||||
// Reconstruct `Program` & config string from serialized program
|
||||
let program = swc_plugin::Serialized::deserialize(&serialized_program);
|
||||
let config = swc_plugin::Serialized::deserialize(&serialized_config);
|
||||
let context = swc_plugin::Serialized::deserialize(&serialized_context);
|
||||
|
||||
// Host (SWC) should allocate memory, copy bytes and pass ptr to plugin.
|
||||
let program = unsafe { swc_plugin::Serialized::deserialize_from_ptr(ast_ptr, ast_ptr_len) };
|
||||
if program.is_err() {
|
||||
let err = swc_plugin::PluginError::Deserialize(
|
||||
("Failed to deserialize program received from host".to_string(),
|
||||
raw_ast_serialized_bytes.to_vec())
|
||||
);
|
||||
let err = swc_plugin::PluginError::Deserialize("Failed to deserialize program received from host".to_string());
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
let program: Program = program.expect("Should be a program");
|
||||
|
||||
let config = unsafe { swc_plugin::Serialized::deserialize_from_ptr(config_str_ptr, config_str_ptr_len) };
|
||||
if config.is_err() {
|
||||
let err = swc_plugin::PluginError::Deserialize(
|
||||
("Failed to deserialize config string received from host".to_string(),
|
||||
raw_config_serialized_bytes.to_vec())
|
||||
"Failed to deserialize config string received from host".to_string()
|
||||
);
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
let config: String = config.expect("Should be a string");
|
||||
|
||||
let context = unsafe { swc_plugin::Serialized::deserialize_from_ptr(context_str_ptr, context_str_ptr_len) };
|
||||
if context.is_err() {
|
||||
let err = swc_plugin::PluginError::Deserialize(
|
||||
("Failed to deserialize context string received from host".to_string(),
|
||||
raw_context_serialized_bytes.to_vec())
|
||||
);
|
||||
let err = swc_plugin::PluginError::Deserialize("Failed to deserialize context string received from host".to_string());
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
let context: String = context.expect("Should be a string");
|
||||
@ -128,7 +88,7 @@ fn handle_func(func: ItemFn) -> TokenStream {
|
||||
let handler = swc_plugin::errors::Handler::with_emitter(
|
||||
true,
|
||||
false,
|
||||
Box::new(swc_plugin::environment::PluginDiagnosticsEmitter {})
|
||||
Box::new(swc_plugin::environment::PluginDiagnosticsEmitter)
|
||||
);
|
||||
let handler_set_result = swc_plugin::errors::HANDLER.inner.set(handler);
|
||||
|
||||
@ -139,8 +99,16 @@ fn handle_func(func: ItemFn) -> TokenStream {
|
||||
return construct_error_ptr(err);
|
||||
}
|
||||
|
||||
// Construct metadata to the `Program` for the transform plugin.
|
||||
let plugin_comments_proxy = if should_enable_comments_proxy == 1 { Some(swc_plugin::comments::PluginCommentsProxy) } else { None };
|
||||
let mut metadata = swc_plugin::TransformPluginProgramMetadata {
|
||||
comments: plugin_comments_proxy,
|
||||
plugin_config: config,
|
||||
transform_context: context
|
||||
};
|
||||
|
||||
// Take original plugin fn ident, then call it with interop'ed args
|
||||
let transformed_program = #ident(program, config, context);
|
||||
let transformed_program = #ident(program, metadata);
|
||||
|
||||
// Serialize transformed result, return back to the host.
|
||||
let serialized_result = swc_plugin::Serialized::serialize(&transformed_program);
|
||||
|
@ -27,6 +27,9 @@ swc_common = { version = "0.17.0", path = "../swc_common", features = [
|
||||
"plugin-rt",
|
||||
"concurrent",
|
||||
] }
|
||||
swc_plugin_comments = { version = "0.1.0", path = "../swc_plugin_comments", features = [
|
||||
"plugin-rt",
|
||||
] }
|
||||
swc_ecma_ast = { version = "0.73.0", path = "../swc_ecma_ast", features = [
|
||||
"rkyv-impl",
|
||||
] }
|
||||
|
@ -1,15 +0,0 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use wasmer::Memory;
|
||||
|
||||
#[derive(wasmer::WasmerEnv, Clone)]
|
||||
/// An external enviornment state imported (declared in host, injected into
|
||||
/// guest) fn can access. This'll allow host access updated state via plugin's
|
||||
/// transform.
|
||||
/// ref: https://docs.wasmer.io/integrations/examples/host-functions#declaring-the-data
|
||||
pub struct HostEnvironment {
|
||||
#[wasmer(export)]
|
||||
pub memory: wasmer::LazyInit<Memory>,
|
||||
pub transform_result: Arc<Mutex<Vec<u8>>>,
|
||||
}
|
29
crates/swc_plugin_runner/src/host_environment.rs
Normal file
29
crates/swc_plugin_runner/src/host_environment.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use wasmer::{LazyInit, Memory, NativeFunc};
|
||||
|
||||
#[derive(wasmer::WasmerEnv, Clone)]
|
||||
/// An external enviornment state imported (declared in host, injected into
|
||||
/// guest) fn can access. This'll allow host access updated state via plugin's
|
||||
/// transform.
|
||||
/// ref: https://docs.wasmer.io/integrations/examples/host-functions#declaring-the-data
|
||||
pub struct HostEnvironment {
|
||||
#[wasmer(export)]
|
||||
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 {
|
||||
pub fn new(transform_result: &Arc<Mutex<Vec<u8>>>) -> HostEnvironment {
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
alloc_guest_memory: LazyInit::default(),
|
||||
}
|
||||
}
|
||||
}
|
72
crates/swc_plugin_runner/src/imported_fn/comments.rs
Normal file
72
crates/swc_plugin_runner/src/imported_fn/comments.rs
Normal file
@ -0,0 +1,72 @@
|
||||
use swc_common::{comments::Comments, plugin::Serialized, BytePos};
|
||||
use swc_plugin_comments::{CommentsVecPtr, HostCommentsStorage, COMMENTS};
|
||||
|
||||
use crate::{host_environment::HostEnvironment, memory_interop::write_into_memory_view};
|
||||
|
||||
/// 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: &HostEnvironment,
|
||||
byte_pos: u32,
|
||||
allocated_ret_ptr: i32,
|
||||
) -> i32 {
|
||||
if let Some(memory) = env.memory_ref() {
|
||||
if let Some(alloc_guest_memory) = env.alloc_guest_memory_ref() {
|
||||
if !COMMENTS.is_set() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return COMMENTS.with(|storage: &HostCommentsStorage| {
|
||||
if let Some(comments) = &storage.inner {
|
||||
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");
|
||||
|
||||
let serialized_bytes_len =
|
||||
serialized_leading_comments_vec_bytes.as_ref().len();
|
||||
|
||||
let (allocated_ptr, allocated_ptr_len) = write_into_memory_view(
|
||||
memory,
|
||||
&serialized_leading_comments_vec_bytes,
|
||||
|_| {
|
||||
// In most cases our host-plugin tranmpoline works in a way that
|
||||
// plugin pre-allocates
|
||||
// memory before calling host imported fn. But in case of
|
||||
// comments return value is Vec<Comments> which
|
||||
// guest cannot predetermine size to allocate, intead
|
||||
// let host allocate by calling guest's alloc via attached
|
||||
// hostenvironment.
|
||||
alloc_guest_memory
|
||||
.call(
|
||||
serialized_bytes_len
|
||||
.try_into()
|
||||
.expect("Should be able to convert size"),
|
||||
)
|
||||
.expect("Should able to allocate memory in the plugin")
|
||||
},
|
||||
);
|
||||
|
||||
// Retuning (allocated_ptr, len) into caller (plugin)
|
||||
let comment_ptr_serialized = Serialized::serialize(&CommentsVecPtr(
|
||||
allocated_ptr,
|
||||
allocated_ptr_len,
|
||||
))
|
||||
.expect("Should be serializable");
|
||||
|
||||
write_into_memory_view(memory, &comment_ptr_serialized, |_| {
|
||||
allocated_ret_ptr
|
||||
});
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
0
|
||||
});
|
||||
}
|
||||
}
|
||||
0
|
||||
}
|
23
crates/swc_plugin_runner/src/imported_fn/handler.rs
Normal file
23
crates/swc_plugin_runner/src/imported_fn/handler.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use swc_common::{
|
||||
errors::{Diagnostic, HANDLER},
|
||||
plugin::Serialized,
|
||||
};
|
||||
|
||||
use crate::{host_environment::HostEnvironment, memory_interop::copy_bytes_into_host};
|
||||
|
||||
pub fn emit_diagnostics(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||
if let Some(memory) = env.memory_ref() {
|
||||
if HANDLER.is_set() {
|
||||
HANDLER.with(|handler| {
|
||||
let diagnostics_bytes = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||
let serialized = Serialized::new_for_plugin(&diagnostics_bytes[..], bytes_ptr_len);
|
||||
let diagnostic = Serialized::deserialize::<Diagnostic>(&serialized)
|
||||
.expect("Should able to be deserialized into diagnsotic");
|
||||
|
||||
let mut builder =
|
||||
swc_common::errors::DiagnosticBuilder::new_diagnostic(handler, diagnostic);
|
||||
builder.emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
@ -1,46 +1,6 @@
|
||||
//! Functions imported into the guests (plugin) runtime allows interop between
|
||||
//! host's state to plugin.
|
||||
//! All of these fn is being called inside of guest's memory space, which calls
|
||||
//! appropriate host fn as needed.
|
||||
use swc_common::{hygiene::MutableMarkContext, plugin::Serialized, Mark, SyntaxContext};
|
||||
|
||||
use swc_common::{
|
||||
errors::{Diagnostic, HANDLER},
|
||||
hygiene::MutableMarkContext,
|
||||
plugin::Serialized,
|
||||
Mark, SyntaxContext,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
context::HostEnvironment,
|
||||
memory_interop::{copy_bytes_into_host, write_into_memory_view},
|
||||
};
|
||||
|
||||
/// Set plugin's transformed result into host's enviroment.
|
||||
/// 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
|
||||
/// this to set its result back to host.
|
||||
pub fn set_transform_result(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||
if let Some(memory) = env.memory_ref() {
|
||||
(*env.transform_result.lock()) = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn emit_diagnostics(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||
if let Some(memory) = env.memory_ref() {
|
||||
if HANDLER.is_set() {
|
||||
HANDLER.with(|handler| {
|
||||
let diagnostics_bytes = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||
let serialized = Serialized::new_for_plugin(&diagnostics_bytes[..], bytes_ptr_len);
|
||||
let diagnostic = Serialized::deserialize::<Diagnostic>(&serialized)
|
||||
.expect("Should able to be deserialized into diagnsotic");
|
||||
|
||||
let mut builder =
|
||||
swc_common::errors::DiagnosticBuilder::new_diagnostic(handler, diagnostic);
|
||||
builder.emit();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
use crate::{host_environment::HostEnvironment, memory_interop::write_into_memory_view};
|
||||
|
||||
/// A proxy to Mark::fresh() that can be used in plugin.
|
||||
/// This it not direcly called by plugin, instead `impl Mark` will selectively
|
136
crates/swc_plugin_runner/src/imported_fn/mod.rs
Normal file
136
crates/swc_plugin_runner/src/imported_fn/mod.rs
Normal file
@ -0,0 +1,136 @@
|
||||
//! Functions for syntax_pos::hygiene imported into the guests (plugin) runtime
|
||||
//! allows interop between host's state to plugin. When guest calls these fn,
|
||||
//! it'll be executed in host's memory space.
|
||||
/*
|
||||
* Below diagram shows one reference example how guest does trampoline between
|
||||
* host's memory space.
|
||||
*┌───────────────────────────────────────┐ ┌─────────────────────────────────────────────┐
|
||||
*│Host (SWC/core) │ │Plugin (wasm) │
|
||||
*│ ┌────────────────────────────────┐ │ │ │
|
||||
*│ │COMMENTS.with() │ │ │ ┌──────────────────────────────────────┐ │
|
||||
*│ │ │ │ │ │PluginCommentsProxy │ │
|
||||
*│ │ │ │ │ │ │ │
|
||||
*│ │ ┌────────────────────────────┐ │ │ │ │ ┌────────────────────────────────┐ │ │
|
||||
*│ │ │get_leading_comments_proxy()│◀┼───┼────┼──┼─┤get_leading() │ │ │
|
||||
*│ │ │ │ │ │ │ │ │ │ │ │
|
||||
*│ │ │ │ │ │ │ │ │ ┌──────────────────────────┐ │ │ │
|
||||
*│ │ │ │─┼───┼──┬─┼──┼─┼─▶CommentsVecPtr(ptr, len) │ │ │ │
|
||||
*│ │ └────────────────────────────┘ │ │ │ │ │ │ │ │ │ │ │
|
||||
*│ │ │ │ │ │ │ │ └─────────────┬────────────┘ │ │ │
|
||||
*│ │ │ │ │ │ │ │ │ │ │ │
|
||||
*│ │ │ │ │ │ │ │ ┌─────────────▼────────────┐ │ │ │
|
||||
*│ └────────────────────────────────┘ │ │ │ │ │ │Vec<Comments> │ │ │ │
|
||||
*│ │ └─┼──┼─┼─▶ │ │ │ │
|
||||
*│ │ │ │ │ └──────────────────────────┘ │ │ │
|
||||
*│ │ │ │ └────────────────────────────────┘ │ │
|
||||
*│ │ │ └──────────────────────────────────────┘ │
|
||||
*└───────────────────────────────────────┘ └─────────────────────────────────────────────┘
|
||||
|
||||
* 1. Plugin calls `PluginCommentsProxy::get_leading()`. PluginCommentsProxy is
|
||||
* a struct constructed in plugin's memory space.
|
||||
* 2. `get_leading()` internally calls `__get_leading_comments_proxy`, which is
|
||||
* imported fn `get_leading_comments_proxy` exists in the host.
|
||||
* 3. Host access necessary values in its memory space (COMMENTS)
|
||||
* 4. Host copies value to be returned into plguin's memory space. Memory
|
||||
* allocation for the value should be manually performed.
|
||||
* 5. Host completes imported fn, `PluginCommentsProxy::get_leading()` now can
|
||||
* read, deserialize memory host wrote.
|
||||
* - In case of `get_leading`, returned value is non-deterministic vec
|
||||
* (`Vec<Comments>`) guest cannot preallocate with specific length. Instead,
|
||||
* guest passes a fixed size struct (CommentsVecPtr), once host allocates
|
||||
* actual vec into guest it'll write pointer to the vec into the struct.
|
||||
*/
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use parking_lot::Mutex;
|
||||
use wasmer::{imports, Function, ImportObject, Module};
|
||||
|
||||
use crate::{host_environment::HostEnvironment, imported_fn::comments::get_leading_comments_proxy};
|
||||
|
||||
mod comments;
|
||||
mod handler;
|
||||
mod hygiene;
|
||||
mod set_transform_result;
|
||||
|
||||
use handler::*;
|
||||
use hygiene::*;
|
||||
use set_transform_result::*;
|
||||
|
||||
/// Create an ImportObject includes functions to be imported from host to the
|
||||
/// plugins.
|
||||
pub(crate) fn build_import_object(
|
||||
module: &Module,
|
||||
transform_result: &Arc<Mutex<Vec<u8>>>,
|
||||
) -> ImportObject {
|
||||
let wasmer_store = module.store();
|
||||
|
||||
// transfrom_result
|
||||
let set_transform_result_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
set_transform_result,
|
||||
);
|
||||
|
||||
// handler
|
||||
let emit_diagnostics_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
emit_diagnostics,
|
||||
);
|
||||
|
||||
// hygiene
|
||||
let mark_fresh_fn_decl = Function::new_native(wasmer_store, mark_fresh_proxy);
|
||||
let mark_parent_fn_decl = Function::new_native(wasmer_store, mark_parent_proxy);
|
||||
let mark_is_builtin_fn_decl = Function::new_native(wasmer_store, mark_is_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(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
mark_is_descendant_of_proxy,
|
||||
);
|
||||
|
||||
let mark_least_ancestor_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
mark_least_ancestor_proxy,
|
||||
);
|
||||
|
||||
let syntax_context_apply_mark_fn_decl =
|
||||
Function::new_native(wasmer_store, syntax_context_apply_mark_proxy);
|
||||
let syntax_context_remove_mark_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
syntax_context_remove_mark_proxy,
|
||||
);
|
||||
let syntax_context_outer_fn_decl =
|
||||
Function::new_native(wasmer_store, syntax_context_outer_proxy);
|
||||
|
||||
// comments
|
||||
let get_leading_comments_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment::new(transform_result),
|
||||
get_leading_comments_proxy,
|
||||
);
|
||||
|
||||
imports! {
|
||||
"env" => {
|
||||
// transform
|
||||
"__set_transform_result" => set_transform_result_fn_decl,
|
||||
// handler
|
||||
"__emit_diagnostics" => emit_diagnostics_fn_decl,
|
||||
// hygiene
|
||||
"__mark_fresh_proxy" => mark_fresh_fn_decl,
|
||||
"__mark_parent_proxy" => mark_parent_fn_decl,
|
||||
"__mark_is_builtin_proxy" => mark_is_builtin_fn_decl,
|
||||
"__mark_set_builtin_proxy" => mark_set_builtin_fn_decl,
|
||||
"__mark_is_descendant_of_proxy" => mark_is_descendant_of_fn_decl,
|
||||
"__mark_least_ancestor" => mark_least_ancestor_fn_decl,
|
||||
"__syntax_context_apply_mark_proxy" => syntax_context_apply_mark_fn_decl,
|
||||
"__syntax_context_remove_mark_proxy" => syntax_context_remove_mark_fn_decl,
|
||||
"__syntax_context_outer_proxy" => syntax_context_outer_fn_decl,
|
||||
// comments
|
||||
"__get_leading_comments_proxy" => get_leading_comments_fn_decl,
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,11 @@
|
||||
use crate::{host_environment::HostEnvironment, memory_interop::copy_bytes_into_host};
|
||||
|
||||
/// Set plugin's transformed result into host's enviroment.
|
||||
/// 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
|
||||
/// this to set its result back to host.
|
||||
pub fn set_transform_result(env: &HostEnvironment, bytes_ptr: i32, bytes_ptr_len: i32) {
|
||||
if let Some(memory) = env.memory_ref() {
|
||||
(*env.transform_result.lock()) = copy_bytes_into_host(memory, bytes_ptr, bytes_ptr_len);
|
||||
}
|
||||
}
|
@ -6,7 +6,7 @@ use swc_common::plugin::Serialized;
|
||||
use transform_executor::TransformExecutor;
|
||||
|
||||
pub mod cache;
|
||||
mod context;
|
||||
mod host_environment;
|
||||
mod imported_fn;
|
||||
mod load_plugin;
|
||||
mod memory_interop;
|
||||
@ -20,11 +20,17 @@ pub fn apply_transform_plugin(
|
||||
program: Serialized,
|
||||
config_json: Serialized,
|
||||
context_json: Serialized,
|
||||
should_enable_comments_proxy: bool,
|
||||
) -> Result<Serialized, Error> {
|
||||
(|| -> Result<_, Error> {
|
||||
let mut transform_tracker = TransformExecutor::new(path, cache)?;
|
||||
|
||||
transform_tracker.transform(&program, &config_json, &context_json)
|
||||
let should_enable_comments_proxy = if should_enable_comments_proxy { 1 } else { 0 };
|
||||
transform_tracker.transform(
|
||||
&program,
|
||||
&config_json,
|
||||
&context_json,
|
||||
should_enable_comments_proxy,
|
||||
)
|
||||
})()
|
||||
.with_context(|| {
|
||||
format!(
|
||||
|
@ -2,18 +2,10 @@ use std::sync::Arc;
|
||||
|
||||
use anyhow::{Context, Error};
|
||||
use parking_lot::Mutex;
|
||||
use wasmer::{imports, ChainableNamedResolver, Function, Instance, LazyInit};
|
||||
use wasmer::{ChainableNamedResolver, Instance};
|
||||
use wasmer_wasi::{is_wasi_module, WasiState};
|
||||
|
||||
use crate::{
|
||||
context::HostEnvironment,
|
||||
imported_fn::{
|
||||
emit_diagnostics, mark_fresh_proxy, mark_is_builtin_proxy, mark_is_descendant_of_proxy,
|
||||
mark_least_ancestor_proxy, mark_parent_proxy, mark_set_builtin_proxy, set_transform_result,
|
||||
syntax_context_apply_mark_proxy, syntax_context_outer_proxy,
|
||||
syntax_context_remove_mark_proxy,
|
||||
},
|
||||
};
|
||||
use crate::imported_fn::build_import_object;
|
||||
|
||||
#[tracing::instrument(level = "info", skip_all)]
|
||||
pub fn load_plugin(
|
||||
@ -24,77 +16,8 @@ pub fn load_plugin(
|
||||
|
||||
return match module {
|
||||
Ok(module) => {
|
||||
let wasmer_store = module.store();
|
||||
let transform_result: Arc<Mutex<Vec<u8>>> = Arc::new(Mutex::new(vec![]));
|
||||
let set_transform_result_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
},
|
||||
set_transform_result,
|
||||
);
|
||||
|
||||
let emit_diagnostics_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
},
|
||||
emit_diagnostics,
|
||||
);
|
||||
|
||||
let mark_fresh_fn_decl = Function::new_native(wasmer_store, mark_fresh_proxy);
|
||||
let mark_parent_fn_decl = Function::new_native(wasmer_store, mark_parent_proxy);
|
||||
let mark_is_builtin_fn_decl = Function::new_native(wasmer_store, mark_is_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(
|
||||
wasmer_store,
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
},
|
||||
mark_is_descendant_of_proxy,
|
||||
);
|
||||
|
||||
let mark_least_ancestor_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
},
|
||||
mark_least_ancestor_proxy,
|
||||
);
|
||||
|
||||
let syntax_context_apply_mark_fn_decl =
|
||||
Function::new_native(wasmer_store, syntax_context_apply_mark_proxy);
|
||||
let syntax_context_remove_mark_fn_decl = Function::new_native_with_env(
|
||||
wasmer_store,
|
||||
HostEnvironment {
|
||||
memory: LazyInit::default(),
|
||||
transform_result: transform_result.clone(),
|
||||
},
|
||||
syntax_context_remove_mark_proxy,
|
||||
);
|
||||
let syntax_context_outer_fn_decl =
|
||||
Function::new_native(wasmer_store, syntax_context_outer_proxy);
|
||||
|
||||
let import_object = imports! {
|
||||
"env" => {
|
||||
"__set_transform_result" => set_transform_result_fn_decl,
|
||||
"__emit_diagnostics" => emit_diagnostics_fn_decl,
|
||||
"__mark_fresh_proxy" => mark_fresh_fn_decl,
|
||||
"__mark_parent_proxy" => mark_parent_fn_decl,
|
||||
"__mark_is_builtin_proxy" => mark_is_builtin_fn_decl,
|
||||
"__mark_set_builtin_proxy" => mark_set_builtin_fn_decl,
|
||||
"__mark_is_descendant_of_proxy" => mark_is_descendant_of_fn_decl,
|
||||
"__mark_least_ancestor" => mark_least_ancestor_fn_decl,
|
||||
"__syntax_context_apply_mark_proxy" => syntax_context_apply_mark_fn_decl,
|
||||
"__syntax_context_remove_mark_proxy" => syntax_context_remove_mark_fn_decl,
|
||||
"__syntax_context_outer_proxy" => syntax_context_outer_fn_decl
|
||||
}
|
||||
};
|
||||
let import_object = build_import_object(&module, &transform_result);
|
||||
|
||||
// Plugin binary can be either wasm32-wasi or wasm32-unknown-unknown.
|
||||
// Wasi specific env need to be initialized if given module targets wasm32-wasi.
|
||||
|
@ -10,7 +10,7 @@ use crate::memory_interop::write_into_memory_view;
|
||||
/// A struct encapsule executing a plugin's transform interop to its teardown
|
||||
pub struct TransformExecutor {
|
||||
// Main transform interface plugin exports
|
||||
exported_plugin_transform: wasmer::NativeFunc<(i32, i32, i32, i32, i32, i32), i32>,
|
||||
exported_plugin_transform: wasmer::NativeFunc<(i32, i32, i32, i32, i32, i32, i32), i32>,
|
||||
// `__free` function automatically exported via swc_plugin sdk to allow deallocation in guest
|
||||
// memory space
|
||||
exported_plugin_free: wasmer::NativeFunc<(i32, i32), i32>,
|
||||
@ -34,7 +34,7 @@ impl TransformExecutor {
|
||||
let tracker = TransformExecutor {
|
||||
exported_plugin_transform: instance
|
||||
.exports
|
||||
.get_native_function::<(i32, i32, i32, i32, i32, i32), i32>(
|
||||
.get_native_function::<(i32, i32, i32, i32, i32, i32, i32), i32>(
|
||||
"__plugin_process_impl",
|
||||
)?,
|
||||
exported_plugin_free: instance
|
||||
@ -85,7 +85,7 @@ impl TransformExecutor {
|
||||
"Failed to convert pointer size to calculate: {}",
|
||||
msg
|
||||
)),
|
||||
PluginError::Deserialize((msg, ..)) | PluginError::Serialize(msg) => {
|
||||
PluginError::Deserialize(msg) | PluginError::Serialize(msg) => {
|
||||
Err(anyhow!("{}", msg))
|
||||
}
|
||||
_ => Err(anyhow!(
|
||||
@ -101,6 +101,7 @@ impl TransformExecutor {
|
||||
program: &Serialized,
|
||||
config: &Serialized,
|
||||
context: &Serialized,
|
||||
should_enable_comments_proxy: i32,
|
||||
) -> Result<Serialized, Error> {
|
||||
let guest_program_ptr = self.write_bytes_into_guest(program)?;
|
||||
let config_str_ptr = self.write_bytes_into_guest(config)?;
|
||||
@ -113,6 +114,7 @@ impl TransformExecutor {
|
||||
config_str_ptr.1,
|
||||
context_str_ptr.0,
|
||||
context_str_ptr.1,
|
||||
should_enable_comments_proxy,
|
||||
)?;
|
||||
|
||||
self.read_bytes_from_guest(result)
|
||||
|
@ -94,6 +94,7 @@ fn internal() -> Result<(), Error> {
|
||||
program,
|
||||
config,
|
||||
context,
|
||||
false,
|
||||
)
|
||||
.expect("Plugin should apply transform");
|
||||
|
||||
@ -142,6 +143,7 @@ fn internal() -> Result<(), Error> {
|
||||
program,
|
||||
config,
|
||||
context,
|
||||
false,
|
||||
)
|
||||
.expect("Plugin should apply transform")
|
||||
});
|
||||
@ -176,6 +178,7 @@ fn internal() -> Result<(), Error> {
|
||||
Serialized::serialize(&"{}".to_string()).expect("Should serializable"),
|
||||
Serialized::serialize(&"{sourceFileName: 'multiple_plugin_test'}".to_string())
|
||||
.expect("Should serializable"),
|
||||
false,
|
||||
)
|
||||
.expect("Plugin should apply transform");
|
||||
|
||||
@ -188,6 +191,7 @@ fn internal() -> Result<(), Error> {
|
||||
Serialized::serialize(&"{}".to_string()).expect("Should serializable"),
|
||||
Serialized::serialize(&"{sourceFileName: 'multiple_plugin_test2'}".to_string())
|
||||
.expect("Should serializable"),
|
||||
false,
|
||||
)
|
||||
.expect("Plugin should apply transform");
|
||||
|
||||
|
385
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
385
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
@ -18,7 +18,7 @@ version = "0.7.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
|
||||
dependencies = [
|
||||
"getrandom 0.2.3",
|
||||
"getrandom",
|
||||
"once_cell",
|
||||
"version_check",
|
||||
]
|
||||
@ -63,6 +63,15 @@ dependencies = [
|
||||
"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]]
|
||||
name = "bitflags"
|
||||
version = "1.3.2"
|
||||
@ -90,27 +99,12 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cloudabi"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4344512281c643ae7638bbabc3af17a11307803ec8f0fcad9fae512a8bf36467"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.13.1"
|
||||
@ -161,16 +155,6 @@ version = "1.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
|
||||
|
||||
[[package]]
|
||||
name = "enum_kind"
|
||||
version = "0.2.1"
|
||||
dependencies = [
|
||||
"pmutil",
|
||||
"proc-macro2",
|
||||
"swc_macros_common",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
@ -197,33 +181,22 @@ dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.11.2"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e"
|
||||
checksum = "8c21d40587b92fa6a6c6e3c1bdbf87d75511db5672f9c93175574b3a00df1758"
|
||||
dependencies = [
|
||||
"ahash",
|
||||
]
|
||||
@ -245,25 +218,6 @@ dependencies = [
|
||||
"unicode-normalization",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282a6247722caba404c065016bbfa522806e51714c34f5dfc3e4a3a46fcb4223"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "is-macro"
|
||||
version = "0.2.0"
|
||||
@ -283,79 +237,6 @@ version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||
|
||||
[[package]]
|
||||
name = "lexical"
|
||||
version = "6.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ccd3e434c16f0164124ade12dcdee324fcc3dafb1cad0c7f1d8c2451a1aa6886"
|
||||
dependencies = [
|
||||
"lexical-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "92912c4af2e7d9075be3e5e3122c4d7263855fa6cce34fbece4dd08e5884624d"
|
||||
dependencies = [
|
||||
"lexical-parse-float",
|
||||
"lexical-parse-integer",
|
||||
"lexical-util",
|
||||
"lexical-write-float",
|
||||
"lexical-write-integer",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-parse-float"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f518eed87c3be6debe6d26b855c97358d8a11bf05acec137e5f53080f5ad2dd8"
|
||||
dependencies = [
|
||||
"lexical-parse-integer",
|
||||
"lexical-util",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-parse-integer"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afc852ec67c6538bbb2b9911116a385b24510e879a69ab516e6a151b15a79168"
|
||||
dependencies = [
|
||||
"lexical-util",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-util"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c72a9d52c5c4e62fa2cdc2cb6c694a39ae1382d9c2a17a466f18e272a0930eb1"
|
||||
dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-write-float"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "26f6202bff3d35ede41a6200227837468bb92e4ecdd437328b1055ed218fb855"
|
||||
dependencies = [
|
||||
"lexical-util",
|
||||
"lexical-write-integer",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lexical-write-integer"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "094060bd2a7c2ff3a16d5304a6ae82727cb3cc9d1c70f813cc73f744c319337e"
|
||||
dependencies = [
|
||||
"lexical-util",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.112"
|
||||
@ -364,9 +245,9 @@ checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.5"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
|
||||
checksum = "88943dd7ef4a2e5a4bfa2753aaab3013e34ce2533d1996fb18ef591e315e2b3b"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
@ -428,28 +309,25 @@ checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
checksum = "87f5ec2493a61ac0506c0f4199f99070cbe83857b0337006a30f3e6719b8ef58"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.0"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c361aa727dd08437f2f1447be8b59a33b0edd15e0fcee698f935613d9efbca9b"
|
||||
checksum = "28141e0cc4143da2443301914478dc976a61ffdb3f043058310c70df2fed8954"
|
||||
dependencies = [
|
||||
"cfg-if 0.1.10",
|
||||
"cloudabi",
|
||||
"instant",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -460,23 +338,14 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.8.0"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526"
|
||||
checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6"
|
||||
dependencies = [
|
||||
"phf_shared 0.8.0",
|
||||
"phf_shared",
|
||||
"rand",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7"
|
||||
dependencies = [
|
||||
"siphasher",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.10.0"
|
||||
@ -555,23 +424,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.7.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
"rand_hc",
|
||||
"rand_pcg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.2.2"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
@ -579,36 +445,21 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.5.1"
|
||||
version = "0.6.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
|
||||
checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
|
||||
dependencies = [
|
||||
"getrandom 0.1.16",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_hc"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_pcg"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429"
|
||||
dependencies = [
|
||||
"rand_core",
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
checksum = "8ae183fc1b06c149f0c1793e1eb447c8b04bfe46d48e9e48bfb8d2d7ed64ecf0"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
@ -638,9 +489,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv"
|
||||
version = "0.7.29"
|
||||
version = "0.7.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49a37de5dfc60bae2d94961dacd03c7b80e426b66a99fa1b17799570dbdd8f96"
|
||||
checksum = "5230ae2981a885590b0dc84e0b24c0ed23ad24f7adc0eb824b26cafa961f7c36"
|
||||
dependencies = [
|
||||
"bytecheck",
|
||||
"hashbrown",
|
||||
@ -652,9 +503,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rkyv_derive"
|
||||
version = "0.7.29"
|
||||
version = "0.7.36"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "719d447dd0e84b23cee6cb5b32d97e21efb112a3e3c636c8da36647b938475a1"
|
||||
checksum = "0fc752d5925dbcb324522f3a4c93193d17f107b2e11810913aa3ad352fa01480"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -717,34 +568,28 @@ version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
|
||||
|
||||
[[package]]
|
||||
name = "static_assertions"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33994d0838dc2d152d17a62adf608a869b5e846b65b389af7f3dbc1de45c5b26"
|
||||
checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"new_debug_unreachable",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"phf_shared 0.10.0",
|
||||
"phf_shared",
|
||||
"precomputed-hash",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "string_cache_codegen"
|
||||
version = "0.5.1"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f24c8e5e19d22a726626f1a5e16fe15b132dcf21d10177fa5a45ce7962996b97"
|
||||
checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988"
|
||||
dependencies = [
|
||||
"phf_generator",
|
||||
"phf_shared 0.8.0",
|
||||
"phf_shared",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
@ -768,7 +613,7 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "swc_atoms"
|
||||
version = "0.2.10"
|
||||
version = "0.2.11"
|
||||
dependencies = [
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
@ -781,8 +626,8 @@ dependencies = [
|
||||
"ahash",
|
||||
"anyhow",
|
||||
"ast_node",
|
||||
"better_scoped_tls",
|
||||
"cfg-if 1.0.0",
|
||||
"better_scoped_tls 0.1.0",
|
||||
"cfg-if",
|
||||
"debug_unreachable",
|
||||
"either",
|
||||
"from_variant",
|
||||
@ -814,64 +659,6 @@ dependencies = [
|
||||
"unicode-id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.97.2"
|
||||
dependencies = [
|
||||
"either",
|
||||
"enum_kind",
|
||||
"lexical",
|
||||
"num-bigint",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"tracing",
|
||||
"typed-arena",
|
||||
"unicode-id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_quote"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_quote_macros",
|
||||
"swc_ecma_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_quote_macros"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"pmutil",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_parser",
|
||||
"swc_macros_common",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.76.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_visit",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_visit"
|
||||
version = "0.59.0"
|
||||
@ -914,16 +701,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin"
|
||||
version = "0.37.0"
|
||||
version = "0.39.0"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_quote",
|
||||
"swc_ecma_visit",
|
||||
"swc_plugin_comments",
|
||||
"swc_plugin_macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin_comments"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"better_scoped_tls 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"rkyv",
|
||||
"swc_common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin_macro"
|
||||
version = "0.3.1"
|
||||
@ -985,7 +781,7 @@ version = "0.1.32"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4a1bdf54a7c28a2bbf701e1d2233f6c77f473486b94bee4f9678da5a148dca7f"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
@ -1011,12 +807,6 @@ dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typed-arena"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-bidi"
|
||||
version = "0.3.7"
|
||||
@ -1083,12 +873,6 @@ version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.9.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.10.2+wasi-snapshot-preview1"
|
||||
@ -1096,23 +880,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
name = "windows-sys"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||
checksum = "3df6e476185f92a12c072be4a189a0210dcdcf512a1891d6dff9edb874deadc6"
|
||||
dependencies = [
|
||||
"winapi-i686-pc-windows-gnu",
|
||||
"winapi-x86_64-pc-windows-gnu",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi-i686-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||
checksum = "d8e92753b1c443191654ec532f14c199742964a061be25d77d7a96f09db20bf5"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-x86_64-pc-windows-gnu"
|
||||
version = "0.4.0"
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
checksum = "6a711c68811799e017b6038e0922cb27a5e2f43a2ddb609fe0b6f3eeda9de615"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "146c11bb1a02615db74680b32a68e2d61f553cc24c4eb5b4ca10311740e44172"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c912b12f7454c6620635bbff3450962753834be2a594819bd5e945af18ec64bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.32.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "504a2476202769977a040c6364301a3f65d0cc9e3fb08600b2bda150a0488316"
|
||||
|
@ -1,4 +1,6 @@
|
||||
use swc_plugin::{ast::*, errors::HANDLER, plugin_transform, syntax_pos::DUMMY_SP};
|
||||
use swc_plugin::{
|
||||
ast::*, errors::HANDLER, plugin_transform, syntax_pos::DUMMY_SP, TransformPluginProgramMetadata,
|
||||
};
|
||||
|
||||
struct ConsoleOutputReplacer;
|
||||
|
||||
@ -33,7 +35,8 @@ impl VisitMut for ConsoleOutputReplacer {
|
||||
/// config_str_ptr: *const u8,
|
||||
/// config_str_ptr_len: i32,
|
||||
/// context_str_ptr: *const u8,
|
||||
/// context_str_ptr_len: i32) ->
|
||||
/// context_str_ptr_len: i32,
|
||||
/// should_enable_comments: i32) ->
|
||||
/// i32 /* 0 for success, fail otherwise.
|
||||
/// Note this is only for internal pointer interop result,
|
||||
/// not actual transform result */
|
||||
@ -42,7 +45,7 @@ impl VisitMut for ConsoleOutputReplacer {
|
||||
/// important steps manually need to be performed like sending transformed
|
||||
/// results back to host. Refer swc_plugin_macro how does it work internally.
|
||||
#[plugin_transform]
|
||||
pub fn process(program: Program, _plugin_config: String, _context: String) -> Program {
|
||||
pub fn process(program: Program, _metadata: TransformPluginProgramMetadata) -> Program {
|
||||
HANDLER.with(|handler| {
|
||||
handler
|
||||
.struct_span_err(DUMMY_SP, "Test diagnostics from plugin")
|
||||
|
Loading…
Reference in New Issue
Block a user