feat(next-swc/wasm): export async interfaces (#39231)

* build(cargo): update dependencies

* feat(next-swc/wasm): export async interfaces

* feat(next/swc): use async wasm binding interface

* refactor(next/swc): allow to fallback for non-async published pkg

* Apply suggestions from code review

Co-authored-by: JJ Kasper <jj@jjsweb.site>
This commit is contained in:
OJ Kwon 2022-08-03 18:55:02 -07:00 committed by GitHub
parent de41597bc8
commit 58b920d5ba
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 86 additions and 46 deletions

View file

@ -1149,9 +1149,9 @@ checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.57" version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@ -4447,6 +4447,7 @@ dependencies = [
"anyhow", "anyhow",
"console_error_panic_hook", "console_error_panic_hook",
"getrandom", "getrandom",
"js-sys",
"next-swc", "next-swc",
"once_cell", "once_cell",
"parking_lot_core 0.8.0", "parking_lot_core 0.8.0",
@ -4466,9 +4467,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.80" version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"serde", "serde",
@ -4478,13 +4479,13 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.80" version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"lazy_static",
"log", "log",
"once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn", "syn",
@ -4505,9 +4506,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.80" version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@ -4515,9 +4516,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.80" version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -4528,9 +4529,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.80" version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
[[package]] [[package]]
name = "wasmer" name = "wasmer"

View file

@ -30,8 +30,9 @@ swc_common = { version = "0.26.0", features = ["concurrent", "sourcemap"] }
swc_ecmascript = { version = "0.186.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] } swc_ecmascript = { version = "0.186.0", features = ["codegen", "minifier", "optimization", "parser", "react", "transforms", "typescript", "utils", "visit"] }
swc_plugin_runner = { version = "0.70.0", default-features = false, optional = true } swc_plugin_runner = { version = "0.70.0", default-features = false, optional = true }
tracing = { version = "0.1.32", features = ["release_max_level_off"] } tracing = { version = "0.1.32", features = ["release_max_level_off"] }
wasm-bindgen = {version = "0.2", features = ["serde-serialize"]} wasm-bindgen = {version = "0.2", features = ["serde-serialize", "enable-interning"]}
wasm-bindgen-futures = "0.4.8" wasm-bindgen-futures = "0.4.8"
wasmer = { version = "2.3.0", optional = true, default-features = false } wasmer = { version = "2.3.0", optional = true, default-features = false }
wasmer-wasi = { version = "2.3.0", optional = true, default-features = false } wasmer-wasi = { version = "2.3.0", optional = true, default-features = false }
getrandom = { version = "0.2.5", optional = true, default-features = false } getrandom = { version = "0.2.5", optional = true, default-features = false }
js-sys = "0.3.59"

View file

@ -1,18 +1,20 @@
use anyhow::{Context, Error}; use anyhow::{Context, Error};
use js_sys::JsString;
use next_swc::{custom_before_pass, TransformOptions}; use next_swc::{custom_before_pass, TransformOptions};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::sync::Arc; use std::sync::Arc;
use swc::{config::JsMinifyOptions, config::ParseOptions, try_with_handler, Compiler}; use swc::{config::JsMinifyOptions, config::ParseOptions, try_with_handler, Compiler};
use swc_common::{comments::Comments, errors::ColorConfig, FileName, FilePathMapping, SourceMap}; use swc_common::{comments::Comments, errors::ColorConfig, FileName, FilePathMapping, SourceMap};
use swc_ecmascript::transforms::pass::noop; use swc_ecmascript::transforms::pass::noop;
use wasm_bindgen::prelude::*; use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_futures::future_to_promise;
fn convert_err(err: Error) -> JsValue { fn convert_err(err: Error) -> JsValue {
format!("{:?}", err).into() format!("{:?}", err).into()
} }
#[wasm_bindgen(js_name = "minifySync")] #[wasm_bindgen(js_name = "minifySync")]
pub fn minify_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> { pub fn minify_sync(s: JsString, opts: JsValue) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
let c = compiler(); let c = compiler();
@ -37,8 +39,15 @@ pub fn minify_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
.map_err(convert_err) .map_err(convert_err)
} }
#[wasm_bindgen(js_name = "minify")]
pub fn minify(s: JsString, opts: JsValue) -> js_sys::Promise {
// TODO: This'll be properly scheduled once wasm have standard backed thread
// support.
future_to_promise(async { minify_sync(s, opts) })
}
#[wasm_bindgen(js_name = "transformSync")] #[wasm_bindgen(js_name = "transformSync")]
pub fn transform_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> { pub fn transform_sync(s: JsValue, opts: JsValue) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
let c = compiler(); let c = compiler();
@ -52,28 +61,39 @@ pub fn transform_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
|handler| { |handler| {
let opts: TransformOptions = opts.into_serde().context("failed to parse options")?; let opts: TransformOptions = opts.into_serde().context("failed to parse options")?;
let fm = c.cm.new_source_file( let s = s.dyn_into::<js_sys::JsString>();
if opts.swc.filename.is_empty() { let out = match s {
FileName::Anon Ok(s) => {
} else { let fm = c.cm.new_source_file(
FileName::Real(opts.swc.filename.clone().into()) if opts.swc.filename.is_empty() {
}, FileName::Anon
s.into(), } else {
); FileName::Real(opts.swc.filename.clone().into())
let cm = c.cm.clone(); },
let file = fm.clone(); s.into(),
let out = c );
.process_js_with_custom_pass( let cm = c.cm.clone();
fm, let file = fm.clone();
None, c.process_js_with_custom_pass(
handler, fm,
&opts.swc, None,
|_, comments| { handler,
custom_before_pass(cm, file, &opts, comments.clone(), Default::default()) &opts.swc,
}, |_, comments| {
|_, _| noop(), custom_before_pass(
) cm,
.context("failed to process js file")?; file,
&opts,
comments.clone(),
Default::default(),
)
},
|_, _| noop(),
)
.context("failed to process js file")?
}
Err(v) => c.process_js(handler, v.into_serde().expect(""), &opts.swc)?,
};
JsValue::from_serde(&out).context("failed to serialize json") JsValue::from_serde(&out).context("failed to serialize json")
}, },
@ -81,8 +101,15 @@ pub fn transform_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
.map_err(convert_err) .map_err(convert_err)
} }
#[wasm_bindgen(js_name = "transform")]
pub fn transform(s: JsValue, opts: JsValue) -> js_sys::Promise {
// TODO: This'll be properly scheduled once wasm have standard backed thread
// support.
future_to_promise(async { transform_sync(s, opts) })
}
#[wasm_bindgen(js_name = "parseSync")] #[wasm_bindgen(js_name = "parseSync")]
pub fn parse_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> { pub fn parse_sync(s: JsString, opts: JsValue) -> Result<JsValue, JsValue> {
console_error_panic_hook::set_once(); console_error_panic_hook::set_once();
let c = swc::Compiler::new(Arc::new(SourceMap::new(FilePathMapping::empty()))); let c = swc::Compiler::new(Arc::new(SourceMap::new(FilePathMapping::empty())));
@ -124,6 +151,13 @@ pub fn parse_sync(s: &str, opts: JsValue) -> Result<JsValue, JsValue> {
.map_err(convert_err) .map_err(convert_err)
} }
#[wasm_bindgen(js_name = "parse")]
pub fn parse(s: JsString, opts: JsValue) -> js_sys::Promise {
// TODO: This'll be properly scheduled once wasm have standard backed thread
// support.
future_to_promise(async { parse_sync(s, opts) })
}
/// Get global sourcemap /// Get global sourcemap
fn compiler() -> Arc<Compiler> { fn compiler() -> Arc<Compiler> {
static C: Lazy<Arc<Compiler>> = Lazy::new(|| { static C: Lazy<Arc<Compiler>> = Lazy::new(|| {

View file

@ -143,22 +143,26 @@ async function loadWasm(importPath = '') {
wasmBindings = { wasmBindings = {
isWasm: true, isWasm: true,
transform(src, options) { transform(src, options) {
return Promise.resolve( // TODO: we can remove fallback to sync interface once new stable version of next-swc gets published (current v12.2)
bindings.transformSync(src.toString(), options) return bindings?.transform
) ? bindings.transform(src.toString(), options)
: Promise.resolve(bindings.transformSync(src.toString(), options))
}, },
transformSync(src, options) { transformSync(src, options) {
return bindings.transformSync(src.toString(), options) return bindings.transformSync(src.toString(), options)
}, },
minify(src, options) { minify(src, options) {
return Promise.resolve(bindings.minifySync(src.toString(), options)) return bindings?.minify
? bindings.minify(src.toString(), options)
: Promise.resolve(bindings.minifySync(src.toString(), options))
}, },
minifySync(src, options) { minifySync(src, options) {
return bindings.minifySync(src.toString(), options) return bindings.minifySync(src.toString(), options)
}, },
parse(src, options) { parse(src, options) {
const astStr = bindings.parseSync(src.toString(), options) return bindings?.parse
return Promise.resolve(astStr) ? bindings.parse(src.toString(), options)
: Promise.resolve(bindings.parseSync(src.toString(), options))
}, },
parseSync(src, options) { parseSync(src, options) {
const astStr = bindings.parseSync(src.toString(), options) const astStr = bindings.parseSync(src.toString(), options)