mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 09:38:16 +03:00
feat(plugin/runner): Implement initial loading for wasm32 (#4151)
This commit is contained in:
parent
51dcfd8c5f
commit
161353cf25
29
Cargo.lock
generated
29
Cargo.lock
generated
@ -1225,9 +1225,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.55"
|
||||
version = "0.3.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
|
||||
checksum = "a38fc24e30fd564ce974c02bf1d337caddff65be6cc4735a1f7eab22a7440f04"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@ -4504,6 +4504,7 @@ version = "1.2.160"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"console_error_panic_hook",
|
||||
"js-sys",
|
||||
"once_cell",
|
||||
"parking_lot_core 0.9.1",
|
||||
"path-clean",
|
||||
@ -4522,9 +4523,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
|
||||
checksum = "25f1af7423d8588a3d840681122e72e6a24ddbcb3f0ec385cac0d12d24256c06"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"serde",
|
||||
@ -4534,9 +4535,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
|
||||
checksum = "8b21c0df030f5a177f3cba22e9bc4322695ec43e7257d865302900290bcdedca"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
@ -4561,9 +4562,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
|
||||
checksum = "2f4203d69e40a52ee523b2529a773d5ffc1dc0071801c87b3d270b471b80ed01"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@ -4571,9 +4572,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
|
||||
checksum = "bfa8a30d46208db204854cadbb5d4baf5fcf8071ba5bf48190c3e59937962ebc"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -4584,9 +4585,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.78"
|
||||
version = "0.2.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
|
||||
checksum = "3d958d035c4438e28c70e4321a2911302f10135ce78a9c7834c0cab4123d06a2"
|
||||
|
||||
[[package]]
|
||||
name = "wasmer"
|
||||
@ -4864,9 +4865,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.55"
|
||||
version = "0.3.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
|
||||
checksum = "c060b319f29dd25724f09a2ba1418f142f539b2be99fbf4d2d5a8f7330afb8eb"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
@ -466,7 +466,7 @@ impl Options {
|
||||
swc_plugin_runner::cache::init_plugin_module_cache_once(&experimental.cache_root);
|
||||
}
|
||||
|
||||
crate::plugin::plugins(plugin_resolver, experimental, plugin_context)
|
||||
crate::plugin::plugins(Some(plugin_resolver), experimental, plugin_context)
|
||||
};
|
||||
|
||||
// Native runtime plugin target, based on assumption we have
|
||||
@ -486,7 +486,8 @@ impl Options {
|
||||
env_name: self.env_name.to_owned(),
|
||||
};
|
||||
|
||||
crate::plugin::plugins(experimental, plugin_context)
|
||||
swc_plugin_runner::cache::init_plugin_module_cache_once();
|
||||
crate::plugin::plugins(None, experimental, plugin_context)
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "plugin"))]
|
||||
|
@ -41,9 +41,9 @@ pub struct PluginContext {
|
||||
pub env_name: String,
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "plugin", not(target_arch = "wasm32")))]
|
||||
#[cfg(feature = "plugin")]
|
||||
pub fn plugins(
|
||||
resolver: CachingResolver<NodeModulesResolver>,
|
||||
resolver: Option<CachingResolver<NodeModulesResolver>>,
|
||||
config: crate::config::JscExperimental,
|
||||
plugin_context: PluginContext,
|
||||
) -> impl Fold {
|
||||
@ -56,18 +56,13 @@ pub fn plugins(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "plugin", target_arch = "wasm32"))]
|
||||
pub fn plugins(config: crate::config::JscExperimental, plugin_context: PluginContext) -> impl Fold {
|
||||
swc_ecma_transforms::pass::noop()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "plugin"))]
|
||||
pub fn plugins() -> impl Fold {
|
||||
noop()
|
||||
}
|
||||
|
||||
struct RustPlugins {
|
||||
resolver: CachingResolver<NodeModulesResolver>,
|
||||
resolver: Option<CachingResolver<NodeModulesResolver>>,
|
||||
plugins: Option<Vec<PluginConfig>>,
|
||||
plugin_context: PluginContext,
|
||||
}
|
||||
@ -109,6 +104,8 @@ impl RustPlugins {
|
||||
|
||||
let resolved_path = self
|
||||
.resolver
|
||||
.as_ref()
|
||||
.expect("filesystem_cache should provide resolver")
|
||||
.resolve(&FileName::Real(PathBuf::from(&p.0)), &p.0)?;
|
||||
|
||||
let path = if let FileName::Real(value) = resolved_path {
|
||||
@ -143,8 +140,36 @@ impl RustPlugins {
|
||||
|
||||
#[cfg(all(feature = "plugin", target_arch = "wasm32"))]
|
||||
fn apply(&mut self, n: Program) -> Result<Program, anyhow::Error> {
|
||||
//not implemented
|
||||
Ok(n)
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use anyhow::Context;
|
||||
use swc_common::{plugin::Serialized, FileName};
|
||||
use swc_ecma_loader::resolve::Resolve;
|
||||
|
||||
let mut serialized = Serialized::serialize(&n)?;
|
||||
|
||||
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))?;
|
||||
|
||||
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 = swc_plugin_runner::apply_transform_plugin(
|
||||
&p.0,
|
||||
&PathBuf::from(&p.0),
|
||||
&swc_plugin_runner::cache::PLUGIN_MODULE_CACHE,
|
||||
serialized,
|
||||
config_json,
|
||||
context_json,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
Serialized::deserialize(&serialized)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,16 +92,18 @@ fn create_filesystem_cache(filesystem_cache_root: &Option<String>) -> Option<Fil
|
||||
///
|
||||
/// If cache failed to initialize filesystem cache for given location
|
||||
/// it'll be serve in-memory cache only.
|
||||
#[cfg(feature = "filesystem_cache")]
|
||||
pub fn init_plugin_module_cache_once(filesystem_cache_root: &Option<String>) {
|
||||
#[cfg(feature = "filesystem_cache")]
|
||||
PLUGIN_MODULE_CACHE.inner.get_or_init(|| {
|
||||
Mutex::new(CacheInner {
|
||||
fs_cache: create_filesystem_cache(filesystem_cache_root),
|
||||
loaded_module_bytes: Default::default(),
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(feature = "memory_cache")]
|
||||
pub fn init_plugin_module_cache_once() {
|
||||
PLUGIN_MODULE_CACHE.inner.get_or_init(|| {
|
||||
Mutex::new(CacheInner {
|
||||
loaded_module_bytes: Default::default(),
|
||||
@ -185,22 +187,27 @@ impl PluginModuleCache {
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(feature = "memory_cache")]
|
||||
pub fn load_module(&self, binary_path: &Path) -> Result<Module, Error> {
|
||||
let binary_path = binary_path.to_path_buf();
|
||||
let mut inner_cache = self.inner.get().expect("Cache should be available").lock();
|
||||
|
||||
// if constructed Module is available in-memory, directly return it.
|
||||
// Note we do not invalidate in-memory cache currently: if wasm binary is
|
||||
// replaced in-process lifecycle (i.e devserver) it won't be reflected.
|
||||
let in_memory_module_bytes = inner_cache.loaded_module_bytes.get(&binary_path);
|
||||
if let Some(module) = in_memory_module_bytes {
|
||||
//TODO: In native runtime we have to reconstruct module using raw bytes in
|
||||
// memory cache. requires https://github.com/wasmerio/wasmer/pull/2821
|
||||
unimplemented!("Not implemented yet");
|
||||
}
|
||||
// In case of memory_cache, we do not have way to resolve / load modules
|
||||
// externally. Bail out if cache doesn't have corresponding binary.
|
||||
let in_memory_module_bytes = inner_cache
|
||||
.loaded_module_bytes
|
||||
.get(&binary_path)
|
||||
.ok_or_else(|| {
|
||||
anyhow::anyhow!("Could not locate plugin binary {}", binary_path.display())
|
||||
})?;
|
||||
|
||||
unimplemented!("Not implemented yet");
|
||||
//TODO: In native runtime we have to reconstruct module using raw bytes in
|
||||
// memory cache. requires https://github.com/wasmerio/wasmer/pull/2821
|
||||
|
||||
let wasmer_store = Store::default();
|
||||
let module = Module::new(&wasmer_store, in_memory_module_bytes)?;
|
||||
|
||||
Ok(module)
|
||||
}
|
||||
|
||||
/// An experimental interface to store externally loaded module bytes into
|
||||
@ -212,7 +219,7 @@ impl PluginModuleCache {
|
||||
///
|
||||
/// This interface is not a public, but also will likely change anytime
|
||||
/// while stablizing plugin interface.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
#[cfg(feature = "memory_cache")]
|
||||
pub fn store_once(&self, module_name: &str, module_bytes: Vec<u8>) {
|
||||
// We use path as canonical id for the cache
|
||||
let binary_path = PathBuf::from(module_name);
|
||||
|
@ -13,7 +13,6 @@ mod memory_interop;
|
||||
mod transform_executor;
|
||||
|
||||
// entrypoint fn swc calls to perform its transform via plugin.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn apply_transform_plugin(
|
||||
plugin_name: &str,
|
||||
path: &Path,
|
||||
@ -35,8 +34,3 @@ pub fn apply_transform_plugin(
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
pub fn apply_transform_plugin() -> Result<Serialized, Error> {
|
||||
unimplemented!("Not implemented yet");
|
||||
}
|
||||
|
@ -15,7 +15,6 @@ use crate::{
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "filesystem_cache")]
|
||||
#[tracing::instrument(level = "info", skip_all)]
|
||||
pub fn load_plugin(
|
||||
plugin_path: &std::path::Path,
|
||||
@ -99,6 +98,8 @@ pub fn load_plugin(
|
||||
|
||||
// Plugin binary can be either wasm32-wasi or wasm32-unknown-unknown.
|
||||
// Wasi specific env need to be initialized if given module targets wasm32-wasi.
|
||||
// TODO: wasm host native runtime throws 'Memory should be set on `WasiEnv`
|
||||
// first'
|
||||
let instance = if is_wasi_module(&module) {
|
||||
// Create the `WasiEnv`.
|
||||
let mut wasi_env = WasiState::new(
|
||||
@ -124,11 +125,3 @@ pub fn load_plugin(
|
||||
Err(err) => Err(err),
|
||||
};
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "filesystem_cache"))]
|
||||
pub fn load_plugin(
|
||||
plugin_path: &std::path::Path,
|
||||
cache: &once_cell::sync::Lazy<crate::cache::PluginModuleCache>,
|
||||
) -> Result<(Instance, Arc<Mutex<Vec<u8>>>), Error> {
|
||||
unimplemented!("not implemented");
|
||||
}
|
||||
|
@ -23,24 +23,26 @@ plugin = [
|
||||
"wasmer-wasi",
|
||||
"wasmer/js-default",
|
||||
"wasmer-wasi/js-default",
|
||||
"js-sys",
|
||||
]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.42"
|
||||
console_error_panic_hook = "0.1.6"
|
||||
js-sys = { version = "0.3.56", optional = true }
|
||||
once_cell = "1.10.0"
|
||||
parking_lot_core = "0.9.1"
|
||||
path-clean = "0.1"
|
||||
serde = {version = "1", features = ["derive"]}
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
swc = {path = "../swc"}
|
||||
swc_common = {path = "../swc_common"}
|
||||
swc_ecma_lints = {path = "../swc_ecma_lints", features = [
|
||||
swc = { path = "../swc" }
|
||||
swc_common = { path = "../swc_common" }
|
||||
swc_ecma_lints = { path = "../swc_ecma_lints", features = [
|
||||
"non_critical_lints",
|
||||
]}
|
||||
swc_ecmascript = {path = "../swc_ecmascript"}
|
||||
swc_plugin_runner = {path = "../swc_plugin_runner", default-features = false, optional = true}
|
||||
tracing = {version = "0.1.32", features = ["release_max_level_off"]}
|
||||
wasm-bindgen = {version = "0.2", features = ["serde-serialize"]}
|
||||
wasmer = {version = "2.2.1", optional = true, default-features = false}
|
||||
wasmer-wasi = {version = "2.2.1", optional = true, default-features = false}
|
||||
] }
|
||||
swc_ecmascript = { path = "../swc_ecmascript" }
|
||||
swc_plugin_runner = { path = "../swc_plugin_runner", default-features = false, optional = true }
|
||||
tracing = { version = "0.1.32", features = ["release_max_level_off"] }
|
||||
wasm-bindgen = { version = "0.2", features = ["serde-serialize"] }
|
||||
wasmer = { version = "2.2.1", optional = true, default-features = false }
|
||||
wasmer-wasi = { version = "2.2.1", optional = true, default-features = false }
|
||||
|
@ -8,7 +8,7 @@ use swc::{
|
||||
};
|
||||
use swc_common::{comments::Comments, FileName, FilePathMapping, SourceMap};
|
||||
use swc_ecmascript::ast::{EsVersion, Program};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use wasm_bindgen::{prelude::*, JsCast};
|
||||
|
||||
fn convert_err(err: Error) -> JsValue {
|
||||
format!("{:?}", err).into()
|
||||
@ -154,23 +154,46 @@ pub fn transform_sync(
|
||||
|
||||
#[cfg(feature = "plugin")]
|
||||
{
|
||||
// TODO: This is probably very inefficient, including each transform
|
||||
// deserializes plugin bytes.
|
||||
let plugin_bytes = if experimental_plugin_bytes_resolver.is_object() {
|
||||
JsValue::into_serde::<std::collections::HashMap<String, Vec<u8>>>(
|
||||
&experimental_plugin_bytes_resolver,
|
||||
)
|
||||
.expect("Object should be available")
|
||||
} else {
|
||||
Default::default()
|
||||
};
|
||||
if experimental_plugin_bytes_resolver.is_object() {
|
||||
use js_sys::{Array, Object, Uint8Array};
|
||||
|
||||
// In here we 'inject' externally loaded bytes into the cache, so remaining
|
||||
// plugin_runner execution path works as much as similar between embedded
|
||||
// runtime.
|
||||
plugin_bytes.into_iter().for_each(|(key, bytes)| {
|
||||
swc_plugin_runner::cache::PLUGIN_MODULE_CACHE.store_once(&key, bytes.clone())
|
||||
});
|
||||
// TODO: This is probably very inefficient, including each transform
|
||||
// deserializes plugin bytes.
|
||||
let plugin_bytes_resolver_object: Object = experimental_plugin_bytes_resolver
|
||||
.try_into()
|
||||
.expect("Resolver should be a js object");
|
||||
|
||||
swc_plugin_runner::cache::init_plugin_module_cache_once();
|
||||
|
||||
let entries = Object::entries(&plugin_bytes_resolver_object);
|
||||
for entry in entries.iter() {
|
||||
let entry: Array = entry
|
||||
.try_into()
|
||||
.expect("Resolver object missing either key or value");
|
||||
let name: String = entry
|
||||
.get(0)
|
||||
.as_string()
|
||||
.expect("Resolver key should be a string");
|
||||
let buffer = entry.get(1);
|
||||
|
||||
//https://github.com/rustwasm/wasm-bindgen/issues/2017#issue-573013044
|
||||
//We may use https://github.com/cloudflare/serde-wasm-bindgen instead later
|
||||
let data = if JsCast::is_instance_of::<Uint8Array>(&buffer) {
|
||||
JsValue::from(Array::from(&buffer))
|
||||
} else {
|
||||
buffer
|
||||
};
|
||||
|
||||
let bytes: Vec<u8> = data
|
||||
.into_serde()
|
||||
.expect("Could not read byte from plugin resolver");
|
||||
|
||||
// In here we 'inject' externally loaded bytes into the cache, so
|
||||
// remaining plugin_runner execution path works as much as
|
||||
// similar between embedded runtime.
|
||||
swc_plugin_runner::cache::PLUGIN_MODULE_CACHE.store_once(&name, bytes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try_with_handler(
|
||||
|
16
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
16
tests/rust-plugins/swc_internal_plugin/Cargo.lock
generated
@ -768,7 +768,7 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "swc_atoms"
|
||||
version = "0.2.9"
|
||||
version = "0.2.10"
|
||||
dependencies = [
|
||||
"string_cache",
|
||||
"string_cache_codegen",
|
||||
@ -802,7 +802,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_ast"
|
||||
version = "0.71.0"
|
||||
version = "0.73.0"
|
||||
dependencies = [
|
||||
"is-macro",
|
||||
"num-bigint",
|
||||
@ -816,7 +816,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.95.2"
|
||||
version = "0.97.2"
|
||||
dependencies = [
|
||||
"either",
|
||||
"enum_kind",
|
||||
@ -834,7 +834,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_quote"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
@ -845,7 +845,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_quote_macros"
|
||||
version = "0.5.0"
|
||||
version = "0.7.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"pmutil",
|
||||
@ -861,7 +861,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_utils"
|
||||
version = "0.74.0"
|
||||
version = "0.76.0"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"once_cell",
|
||||
@ -874,7 +874,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_visit"
|
||||
version = "0.57.0"
|
||||
version = "0.59.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"swc_atoms",
|
||||
@ -914,7 +914,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "swc_plugin"
|
||||
version = "0.35.0"
|
||||
version = "0.37.0"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
|
Loading…
Reference in New Issue
Block a user