diff --git a/Cargo.lock b/Cargo.lock index c5378f291e5d..42393bdc3697 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -174,6 +174,8 @@ dependencies = [ "console_error_panic_hook", "js-sys", "once_cell", + "serde", + "serde-wasm-bindgen", "swc", "swc_common", "swc_ecma_ast", @@ -2655,9 +2657,9 @@ dependencies = [ [[package]] name = "serde-wasm-bindgen" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cfc62771e7b829b517cb213419236475f434fb480eddd76112ae182d274434a" +checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" dependencies = [ "js-sys", "serde", @@ -4915,9 +4917,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d" +checksum = "eaf9f5aceeec8be17c128b2e93e031fb8a4d469bb9c4ae2d7dc1888b26887268" dependencies = [ "cfg-if 1.0.0", "serde", @@ -4927,9 +4929,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f" +checksum = "4c8ffb332579b0557b52d268b91feab8df3615f265d5270fec2a8c95b17c1142" dependencies = [ "bumpalo", "log", @@ -4954,9 +4956,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602" +checksum = "052be0f94026e6cbc75cdefc9bae13fd6052cdcaf532fa6c45e7ae33a1e6c810" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4964,9 +4966,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da" +checksum = "07bc0c051dc5f23e307b13285f9d75df86bfdf816c5721e573dec1f9b8aa193c" dependencies = [ "proc-macro2", "quote", @@ -4977,9 +4979,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.82" +version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a" +checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" [[package]] name = "wasmer" diff --git a/bindings/Cargo.lock b/bindings/Cargo.lock index 3bdc1d03d448..3c322822dd4d 100644 --- a/bindings/Cargo.lock +++ b/bindings/Cargo.lock @@ -179,6 +179,8 @@ name = "binding_core_wasm" version = "1.3.16" dependencies = [ "anyhow", + "serde", + "serde-wasm-bindgen", "swc_core", "tracing", "wasm-bindgen", diff --git a/bindings/binding_core_wasm/Cargo.toml b/bindings/binding_core_wasm/Cargo.toml index 0ed3ca6f6130..f4d56033c910 100644 --- a/bindings/binding_core_wasm/Cargo.toml +++ b/bindings/binding_core_wasm/Cargo.toml @@ -29,9 +29,10 @@ swc_core = { version = "0.43.3", features = [ ] } tracing = { version = "0.1.37", features = ["max_level_off"] } wasm-bindgen = { version = "0.2.82", features = [ - "serde-serialize", "enable-interning", ] } +serde = { version = "1", features = ["derive"] } +serde-wasm-bindgen = "0.4.5" [package.metadata.wasm-pack.profile.release] wasm-opt = false diff --git a/bindings/binding_core_wasm/src/lib.rs b/bindings/binding_core_wasm/src/lib.rs index 9df28d760676..0ecf9f981e46 100644 --- a/bindings/binding_core_wasm/src/lib.rs +++ b/bindings/binding_core_wasm/src/lib.rs @@ -1,4 +1,6 @@ use anyhow::Error; +use serde::Serialize; +use serde_wasm_bindgen::Serializer; use swc_core::{ base::HandlerOpts, binding_macros::wasm::{ @@ -21,6 +23,12 @@ use swc_core::{ use wasm_bindgen::{prelude::*, JsCast}; mod types; +// A serializer with options to provide backward compat for the input / output +// from the bindgen generated swc interfaces. +const COMPAT_SERIALIZER: Serializer = Serializer::new() + .serialize_maps_as_objects(true) + .serialize_missing_as_null(true); + /// Custom interface definitions for the @swc/wasm's public interface instead of /// auto generated one, which is not reflecting most of types in detail. #[wasm_bindgen(typescript_custom_section)] @@ -81,12 +89,16 @@ pub fn minify_sync(s: JsString, opts: JsValue) -> Result { let opts = if opts.is_null() || opts.is_undefined() { Default::default() } else { - anyhow::Context::context(opts.into_serde(), "failed to parse options")? + serde_wasm_bindgen::from_value(opts) + .map_err(|e| anyhow::anyhow!("failed to parse options: {}", e))? }; let fm = c.cm.new_source_file(FileName::Anon, s.into()); let program = anyhow::Context::context(c.minify(fm, handler, &opts), "failed to minify file")?; - anyhow::Context::context(JsValue::from_serde(&program), "failed to serialize json") + + program + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| anyhow::anyhow!("failed to serialize program: {}", e)) }) }) .map_err(|e| convert_err(e, None)) @@ -106,7 +118,8 @@ pub fn parse_sync(s: JsString, opts: JsValue) -> Result { let opts: ParseOptions = if opts.is_null() || opts.is_undefined() { Default::default() } else { - anyhow::Context::context(opts.into_serde(), "failed to parse options")? + serde_wasm_bindgen::from_value(opts) + .map_err(|e| anyhow::anyhow!("failed to parse options: {}", e))? }; let fm = c.cm.new_source_file(FileName::Anon, s.into()); let cmts = c.comments().clone(); @@ -133,7 +146,9 @@ pub fn parse_sync(s: JsString, opts: JsValue) -> Result { opts.syntax.typescript(), )); - anyhow::Context::context(JsValue::from_serde(&program), "failed to serialize json") + program + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| anyhow::anyhow!("failed to serialize program: {}", e)) }) }) }) @@ -160,9 +175,9 @@ pub fn transform_sync( let opts: Options = if opts.is_null() || opts.is_undefined() { Default::default() } else { - anyhow::Context::context(opts.into_serde(), "failed to parse options") - .map_err(|e| convert_err(e, None))? + serde_wasm_bindgen::from_value(opts)? }; + let error_format = opts.experimental.error_format.unwrap_or_default(); try_with_handler(c.cm.clone(), Default::default(), |handler| { c.run(|| { @@ -193,9 +208,13 @@ pub fn transform_sync( "failed to process js file", )? } - Err(v) => unsafe { c.process_js(handler, v.into_serde().expect(""), &opts)? }, + Err(v) => { + c.process_js(handler, serde_wasm_bindgen::from_value(v).expect("Should able to deserialize into program"), &opts)? + } }; - anyhow::Context::context(JsValue::from_serde(&out), "failed to serialize json") + + out.serialize(&COMPAT_SERIALIZER) + .map_err(|e| anyhow::anyhow!("failed to serialize transform result: {}", e)) }) }) .map_err(|e| convert_err(e, Some(error_format))) @@ -218,10 +237,13 @@ pub fn print_sync(s: JsValue, opts: JsValue) -> Result { let opts: Options = if opts.is_null() || opts.is_undefined() { Default::default() } else { - anyhow::Context::context(opts.into_serde(), "failed to parse options")? + serde_wasm_bindgen::from_value(opts) + .map_err(|e| anyhow::anyhow!("failed to parse options: {}", e))? }; - let program: Program = - anyhow::Context::context(s.into_serde(), "failed to deserialize program")?; + + let program: Program = serde_wasm_bindgen::from_value(s) + .map_err(|e| anyhow::anyhow!("failed to deserialize program: {}", e))?; + let s = anyhow::Context::context( c.print( &program, @@ -241,7 +263,9 @@ pub fn print_sync(s: JsValue, opts: JsValue) -> Result { ), "failed to print code", )?; - anyhow::Context::context(JsValue::from_serde(&s), "failed to serialize json") + + serde_wasm_bindgen::to_value(&s) + .map_err(|e| anyhow::anyhow!("failed to serialize json: {}", e)) }) }) .map_err(|e| convert_err(e, None)) diff --git a/crates/binding_macros/Cargo.toml b/crates/binding_macros/Cargo.toml index 13d3ee7fb5d0..aee83f3563a6 100644 --- a/crates/binding_macros/Cargo.toml +++ b/crates/binding_macros/Cargo.toml @@ -40,8 +40,9 @@ anyhow = { optional = true, version = "1.0.58" } console_error_panic_hook = { optional = true, version = "0.1.7" } js-sys = { optional = true, version = "0.3.59" } once_cell = { optional = true, version = "1.13.0" } +serde = { optional = true, version = "1", features = ["derive"] } wasm-bindgen = { optional = true, version = "0.2.82", features = [ - "serde-serialize", "enable-interning", ] } wasm-bindgen-futures = { optional = true, version = "0.4.32" } +serde-wasm-bindgen = { optional = true, version = "0.4.5" } diff --git a/crates/binding_macros/src/wasm.rs b/crates/binding_macros/src/wasm.rs index a5e2aff01d3d..f857b01655a7 100644 --- a/crates/binding_macros/src/wasm.rs +++ b/crates/binding_macros/src/wasm.rs @@ -6,6 +6,8 @@ use anyhow::Error; #[doc(hidden)] pub use js_sys; use once_cell::sync::Lazy; +use serde::Serialize; +use serde_wasm_bindgen::Serializer; use swc::{config::ErrorFormat, Compiler}; #[doc(hidden)] pub use swc::{ @@ -24,6 +26,12 @@ pub use wasm_bindgen::{JsCast, JsValue}; #[doc(hidden)] pub use wasm_bindgen_futures::future_to_promise; +// A serializer with options to provide backward compat for the input / output +// from the bindgen generated swc interfaces. +const COMPAT_SERIALIZER: Serializer = Serializer::new() + .serialize_maps_as_objects(true) + .serialize_missing_as_null(true); + /// Get global sourcemap pub fn compiler() -> Arc { console_error_panic_hook::set_once(); @@ -66,13 +74,16 @@ macro_rules! build_minify_sync { let opts = if opts.is_null() || opts.is_undefined() { Default::default() } else { - $crate::wasm::anyhow::Context::context(opts.into_serde(), "failed to parse options")? + $crate::wasm::serde_wasm_bindgen::from_value(opts) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to parse options: {}", e))? }; let fm = c.cm.new_source_file($crate::wasm::FileName::Anon, s.into()); let program = $crate::wasm::anyhow::Context::context(c.minify(fm, handler, &opts), "failed to minify file")?; - $crate::wasm::anyhow::Context::context($crate::wasm::JsValue::from_serde(&program), "failed to serialize json") + program + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to serialize program: {}", e)) }) }, ) @@ -115,7 +126,8 @@ macro_rules! build_parse_sync { let opts: $crate::wasm::ParseOptions = if opts.is_null() || opts.is_undefined() { Default::default() } else { - $crate::wasm::anyhow::Context::context(opts.into_serde(), "failed to parse options")? + $crate::wasm::serde_wasm_bindgen::from_value(opts) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to parse options: {}", e))? }; let fm = c.cm.new_source_file($crate::wasm::FileName::Anon, s.into()); @@ -140,7 +152,9 @@ macro_rules! build_parse_sync { "failed to parse code" )?; - $crate::wasm::anyhow::Context::context($crate::wasm::JsValue::from_serde(&program), "failed to serialize json") + program + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to serialize program: {}", e)) }) }, ) @@ -183,10 +197,12 @@ macro_rules! build_print_sync { let opts: $crate::wasm::Options = if opts.is_null() || opts.is_undefined() { Default::default() } else { - $crate::wasm::anyhow::Context::context(opts.into_serde(), "failed to parse options")? + $crate::wasm::serde_wasm_bindgen::from_value(opts) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to parse options: {}", e))? }; - let program: $crate::wasm::Program = $crate::wasm::anyhow::Context::context(s.into_serde(), "failed to deserialize program")?; + let program: $crate::wasm::Program = $crate::wasm::serde_wasm_bindgen::from_value(s) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to deserialize program: {}", e))?; let s = $crate::wasm::anyhow::Context::context(c .print( &program, @@ -205,7 +221,9 @@ macro_rules! build_print_sync { false, ),"failed to print code")?; - $crate::wasm::anyhow::Context::context(JsValue::from_serde(&s), "failed to serialize json") + program + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to serialize program: {}", e)) }) }, ) @@ -281,9 +299,7 @@ macro_rules! build_transform_sync { buffer }; - let bytes: Vec = data - .into_serde() - .expect("Could not read byte from plugin resolver"); + let bytes: Vec = $crate::wasm::serde_wasm_bindgen::from_value(data).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 @@ -296,8 +312,7 @@ macro_rules! build_transform_sync { let opts: $crate::wasm::Options = if opts.is_null() || opts.is_undefined() { Default::default() } else { - $crate::wasm::anyhow::Context::context(opts.into_serde(), "failed to parse options") - .map_err(|e| $crate::wasm::convert_err(e, None))? + $crate::wasm::serde_wasm_bindgen::from_value(opts)? }; let error_format = opts.experimental.error_format.unwrap_or_default(); @@ -333,11 +348,12 @@ macro_rules! build_transform_sync { ), "failed to process js file" )? } - Err(v) => unsafe { c.process_js(handler, v.into_serde().expect(""), &opts)? }, + Err(v) => unsafe { c.process_js(handler, $crate::wasm::serde_wasm_bindgen::from_value(v).expect(""), &opts)? }, }; - $crate::wasm::anyhow::Context::context($crate::wasm::JsValue::from_serde(&out), - "failed to serialize json") + out + .serialize(&COMPAT_SERIALIZER) + .map_err(|e| $crate::wasm::anyhow::anyhow!("failed to serialize transform result: {}", e)) }) }, )