Skip to content

Commit

Permalink
feat(plugin/macros): Export new interface for getting plugin schema v…
Browse files Browse the repository at this point in the history
…ersion (swc-project#5166)
  • Loading branch information
kwonoj authored and GiveMe-A-Name committed Jul 23, 2022
1 parent aab6b5b commit 04b945b
Show file tree
Hide file tree
Showing 15 changed files with 94 additions and 10 deletions.
10 changes: 8 additions & 2 deletions .github/workflows/cargo.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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: |
Expand Down
3 changes: 3 additions & 0 deletions crates/binding_core_node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
]
Expand Down
1 change: 1 addition & 0 deletions crates/binding_core_wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
4 changes: 4 additions & 0 deletions crates/swc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
4 changes: 4 additions & 0 deletions crates/swc/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions crates/swc_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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",
]
Expand Down
2 changes: 2 additions & 0 deletions crates/swc_common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
22 changes: 22 additions & 0 deletions crates/swc_common/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
1 change: 1 addition & 0 deletions crates/swc_plugin/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"] }
Expand Down
5 changes: 4 additions & 1 deletion crates/swc_plugin/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
7 changes: 7 additions & 0 deletions crates/swc_plugin_macro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion crates/swc_plugin_runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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",
Expand Down
27 changes: 23 additions & 4 deletions crates/swc_plugin_runner/src/transform_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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>,
Expand Down Expand Up @@ -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")?,
Expand Down Expand Up @@ -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)]
Expand Down
8 changes: 8 additions & 0 deletions crates/swc_plugin_runner/tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))? {
Expand Down
4 changes: 2 additions & 2 deletions tests/rust-plugins/swc_internal_plugin/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 04b945b

Please sign in to comment.