mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 05:32:09 +03:00
feat(plugin/macros): Export new interface for getting plugin schema version (#5166)
This commit is contained in:
parent
793c423a24
commit
f167198470
10
.github/workflows/cargo.yml
vendored
10
.github/workflows/cargo.yml
vendored
@ -115,7 +115,7 @@ jobs:
|
||||
- crate: swc
|
||||
os: ubuntu-latest
|
||||
check: |
|
||||
cargo hack check --feature-powerset --no-dev-deps --exclude-features debug --exclude-features plugin
|
||||
cargo hack check --feature-powerset --no-dev-deps --exclude-features debug --exclude-features plugin --exclude-features plugin-transform-schema-v1
|
||||
- crate: swc
|
||||
os: windows-latest
|
||||
- crate: swc_atoms
|
||||
@ -136,7 +136,7 @@ jobs:
|
||||
- crate: swc_common
|
||||
os: ubuntu-latest
|
||||
check: |
|
||||
cargo hack check --feature-powerset --no-dev-deps
|
||||
cargo hack check --feature-powerset --no-dev-deps --exclude-features plugin-transform-schema-vtest
|
||||
- crate: swc_common
|
||||
os: windows-latest
|
||||
- crate: swc_config
|
||||
@ -398,9 +398,15 @@ jobs:
|
||||
swc-exec-cache-${{ matrix.settings.crate }}-${{ runner.os }}
|
||||
|
||||
- name: Run cargo test
|
||||
if: matrix.settings.crate != 'swc_plugin_runner'
|
||||
run: |
|
||||
cargo test --color always -p ${{ matrix.settings.crate }}
|
||||
|
||||
- name: Run cargo test (plugin)
|
||||
if: matrix.settings.crate == 'swc_plugin_runner'
|
||||
run: |
|
||||
cargo test --color always -p swc_plugin_runner --features plugin-transform-schema-v1
|
||||
|
||||
- name: Run cargo test (all features)
|
||||
if: matrix.settings.crate == 'swc_ecma_parser' || matrix.settings.crate == 'swc_ecma_loader' || matrix.settings.crate == 'swc_ecma_transforms'
|
||||
run: |
|
||||
|
@ -16,7 +16,10 @@ crate-type = ["cdylib"]
|
||||
default = ["swc_v1", "plugin"]
|
||||
plugin = [
|
||||
"swc/plugin",
|
||||
"swc/plugin-transform-schema-v1",
|
||||
"swc_common/plugin-transform-schema-v1",
|
||||
"swc_plugin_runner/default",
|
||||
"swc_plugin_runner/plugin-transform-schema-v1",
|
||||
"wasmer/default",
|
||||
"wasmer-wasi/default",
|
||||
]
|
||||
|
@ -20,6 +20,7 @@ swc_v2 = []
|
||||
plugin = [
|
||||
"swc/plugin",
|
||||
"swc_plugin_runner/memory_cache",
|
||||
"swc_plugin_runner/plugin-transform-schema-v1",
|
||||
"wasmer",
|
||||
"wasmer-wasi",
|
||||
"wasmer/js-default",
|
||||
|
@ -22,6 +22,10 @@ default = ["es3"]
|
||||
es3 = []
|
||||
node = ["napi", "napi-derive"]
|
||||
plugin = ["swc_plugin_runner", "swc_plugin_proxy/plugin-rt"]
|
||||
plugin-transform-schema-v1 = [
|
||||
"swc_common/plugin-transform-schema-v1",
|
||||
"swc_plugin_runner/plugin-transform-schema-v1"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.7.4"
|
||||
|
@ -127,6 +127,10 @@ impl RustPlugins {
|
||||
&self.source_map,
|
||||
)?;
|
||||
|
||||
if !transform_plugin_executor.is_transform_schema_compatible()? {
|
||||
anyhow::bail!("Cannot execute incompatible plugin {}", &p.0);
|
||||
}
|
||||
|
||||
let span = tracing::span!(
|
||||
tracing::Level::INFO,
|
||||
"serialize_context",
|
||||
|
@ -18,6 +18,7 @@ default = []
|
||||
plugin = [
|
||||
"swc/plugin",
|
||||
"swc_plugin_runner/filesystem_cache",
|
||||
"swc_plugin_runner/plugin-transform-schema-v1",
|
||||
"wasmer/default",
|
||||
"wasmer-wasi/default",
|
||||
]
|
||||
|
@ -26,6 +26,8 @@ plugin-mode = ["plugin-base"]
|
||||
plugin-rt = ["plugin-base"]
|
||||
rkyv-impl = ["rkyv", "bytecheck"]
|
||||
tty-emitter = ["atty", "termcolor"]
|
||||
plugin-transform-schema-v1 = []
|
||||
plugin-transform-schema-vtest = []
|
||||
|
||||
[dependencies]
|
||||
ahash = "0.7.4"
|
||||
|
@ -12,6 +12,28 @@ use rkyv::{with::AsBox, Archive, Deserialize, Serialize};
|
||||
|
||||
use crate::{syntax_pos::Mark, SyntaxContext};
|
||||
|
||||
/**
|
||||
* Compile-time version constant for the AST struct schema's version.
|
||||
*
|
||||
* NOTE: this is for PARTIAL compatibility only, supporting if AST struct
|
||||
* adds new properties without changing / removing existing properties.
|
||||
*
|
||||
* - When adding a new properties to the AST struct:
|
||||
* 1. Create a new feature flag in cargo.toml
|
||||
* 2. Create a new schema version with new feature flag.
|
||||
* 3. Create a new AST struct with compile time feature flag with newly
|
||||
* added properties. Previous struct should remain with existing feature
|
||||
* flag, or add previous latest feature flag.
|
||||
*
|
||||
* - When removing, or changing existing properties in the AST struct: TBD
|
||||
*/
|
||||
#[cfg(feature = "plugin-transform-schema-v1")]
|
||||
pub const PLUGIN_TRANSFORM_AST_SCHEMA_VERSION: u32 = 1;
|
||||
|
||||
// Reserved for the testing purpose.
|
||||
#[cfg(feature = "plugin-transform-schema-vtest")]
|
||||
pub const PLUGIN_TRANSFORM_AST_SCHEMA_VERSION: u32 = u32::MAX - 1;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
#[cfg_attr(
|
||||
|
@ -22,6 +22,7 @@ quote = ["swc_ecma_quote"]
|
||||
swc_atoms = { version = "0.2.0", path = "../swc_atoms" }
|
||||
swc_common = { version = "0.23.0", path = "../swc_common", features = [
|
||||
"plugin-mode",
|
||||
"plugin-transform-schema-v1"
|
||||
] }
|
||||
swc_ecma_quote = { version = "0.25.0", path = "../swc_ecma_quote", optional = true }
|
||||
swc_ecmascript = { version = "0.179.0", path = "../swc_ecmascript", features = ["utils", "visit", "rkyv-impl"] }
|
||||
|
@ -3,7 +3,10 @@
|
||||
// Reexports
|
||||
pub use swc_common::{
|
||||
chain,
|
||||
plugin::{deserialize_from_ptr, PluginError, PluginSerializedBytes, VersionedSerializable},
|
||||
plugin::{
|
||||
deserialize_from_ptr, PluginError, PluginSerializedBytes, VersionedSerializable,
|
||||
PLUGIN_TRANSFORM_AST_SCHEMA_VERSION,
|
||||
},
|
||||
};
|
||||
|
||||
pub mod comments {
|
||||
|
@ -21,6 +21,8 @@ fn handle_func(func: ItemFn) -> TokenStream {
|
||||
let ident = func.sig.ident.clone();
|
||||
let transform_process_impl_ident =
|
||||
Ident::new("__transform_plugin_process_impl", Span::call_site());
|
||||
let transform_schema_version_ident =
|
||||
Ident::new("__get_transform_plugin_schema_version", Span::call_site());
|
||||
|
||||
let ret = quote! {
|
||||
#func
|
||||
@ -55,6 +57,11 @@ fn handle_func(func: ItemFn) -> TokenStream {
|
||||
1
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub fn #transform_schema_version_ident() -> u32 {
|
||||
swc_plugin::PLUGIN_TRANSFORM_AST_SCHEMA_VERSION
|
||||
}
|
||||
|
||||
// Macro to allow compose plugin's transform function without manual pointer operation.
|
||||
// Internally it wraps pointer operation also bubbles up error in forms of PluginError.
|
||||
// There are some cases error won't be wrapped up however - for example, we expect
|
||||
|
@ -19,6 +19,9 @@ filesystem_cache = ["wasmer-cache"]
|
||||
# Supports a cache allow to store wasm module in-memory. This avoids recompilation
|
||||
# to the same module in a single procress lifecycle.
|
||||
memory_cache = []
|
||||
plugin-transform-schema-v1 = [
|
||||
"swc_common/plugin-transform-schema-v1"
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.42"
|
||||
@ -28,7 +31,7 @@ serde = { version = "1.0.126", features = ["derive"] }
|
||||
serde_json = "1.0.64"
|
||||
swc_common = { version = "0.23.0", path = "../swc_common", features = [
|
||||
"plugin-rt",
|
||||
"concurrent",
|
||||
"concurrent"
|
||||
] }
|
||||
swc_ecma_ast = { version = "0.84.0", path = "../swc_ecma_ast", features = [
|
||||
"rkyv-impl",
|
||||
|
@ -3,7 +3,7 @@ use std::sync::Arc;
|
||||
use anyhow::{anyhow, Error};
|
||||
use parking_lot::Mutex;
|
||||
use swc_common::{
|
||||
plugin::{PluginError, PluginSerializedBytes},
|
||||
plugin::{PluginError, PluginSerializedBytes, PLUGIN_TRANSFORM_AST_SCHEMA_VERSION},
|
||||
SourceMap,
|
||||
};
|
||||
use wasmer::Instance;
|
||||
@ -14,6 +14,8 @@ use crate::memory_interop::write_into_memory_view;
|
||||
pub struct TransformExecutor {
|
||||
// Main transform interface plugin exports
|
||||
exported_plugin_transform: wasmer::NativeFunc<(i32, i32, i32, i32, i32, i32, i32), i32>,
|
||||
// Schema version interface exports
|
||||
exported_plugin_transform_schema_version: wasmer::NativeFunc<(), u32>,
|
||||
// `__free` function automatically exported via swc_plugin sdk to allow deallocation in guest
|
||||
// memory space
|
||||
exported_plugin_free: wasmer::NativeFunc<(i32, i32), i32>,
|
||||
@ -42,6 +44,9 @@ impl TransformExecutor {
|
||||
.get_native_function::<(i32, i32, i32, i32, i32, i32, i32), i32>(
|
||||
"__transform_plugin_process_impl",
|
||||
)?,
|
||||
exported_plugin_transform_schema_version: instance
|
||||
.exports
|
||||
.get_native_function::<(), u32>("__get_transform_plugin_schema_version")?,
|
||||
exported_plugin_free: instance
|
||||
.exports
|
||||
.get_native_function::<(i32, i32), i32>("__free")?,
|
||||
@ -103,14 +108,28 @@ impl TransformExecutor {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check compile-time versions of AST schema between the plugin and
|
||||
* Check compile-time version of AST schema between the plugin and
|
||||
* the host. Returns true if it's compatible, false otherwise.
|
||||
*
|
||||
* Host should appropriately handle if plugin is not compatible to the
|
||||
* current runtime.
|
||||
*/
|
||||
pub fn is_transform_schema_compatible(&self) -> bool {
|
||||
todo!("Not supported yet");
|
||||
pub fn is_transform_schema_compatible(&self) -> Result<bool, Error> {
|
||||
let plugin_schema_version = self.exported_plugin_transform_schema_version.call();
|
||||
|
||||
match plugin_schema_version {
|
||||
Ok(plugin_schema_version) => {
|
||||
let host_schema_version = PLUGIN_TRANSFORM_AST_SCHEMA_VERSION;
|
||||
|
||||
// TODO: this is incomplete
|
||||
if plugin_schema_version == host_schema_version {
|
||||
Ok(true)
|
||||
} else {
|
||||
Ok(false)
|
||||
}
|
||||
}
|
||||
Err(e) => Err(anyhow!("Failed to call plugin's schema version: {}", e)),
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "info", skip_all)]
|
||||
|
@ -24,6 +24,14 @@ fn build_plugin(dir: &Path) -> Result<PathBuf, Error> {
|
||||
cmd.args(["build", "--target=wasm32-wasi"])
|
||||
.stderr(Stdio::inherit());
|
||||
cmd.output()?;
|
||||
|
||||
if !cmd
|
||||
.status()
|
||||
.expect("Exit code should be available")
|
||||
.success()
|
||||
{
|
||||
return Err(anyhow!("Failed to build plugin"));
|
||||
}
|
||||
}
|
||||
|
||||
for entry in fs::read_dir(&dir.join("target").join("wasm32-wasi").join("debug"))? {
|
||||
|
@ -848,7 +848,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin"
|
||||
version = "0.74.0"
|
||||
version = "0.75.0"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
@ -868,7 +868,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin_proxy"
|
||||
version = "0.8.0"
|
||||
version = "0.9.0"
|
||||
dependencies = [
|
||||
"better_scoped_tls",
|
||||
"bytecheck",
|
||||
|
Loading…
Reference in New Issue
Block a user