diff --git a/bindings/binding_core_wasm/src/lib.rs b/bindings/binding_core_wasm/src/lib.rs index 0ecf9f981e46..f83e498c0c76 100644 --- a/bindings/binding_core_wasm/src/lib.rs +++ b/bindings/binding_core_wasm/src/lib.rs @@ -1,34 +1,10 @@ -use anyhow::Error; -use serde::Serialize; -use serde_wasm_bindgen::Serializer; -use swc_core::{ - base::HandlerOpts, - binding_macros::wasm::{ - compiler, convert_err, future_to_promise, - js_sys::{JsString, Promise}, - noop, Options, ParseOptions, SourceMapsConfig, - }, - common::{ - comments::{self, SingleThreadedComments}, - errors::Handler, - sync::Lrc, - FileName, Mark, SourceMap, GLOBALS, - }, - ecma::{ - ast::{EsVersion, Program}, - transforms::base::resolver, - visit::VisitMutWith, - }, +use swc_core::binding_macros::{ + build_minify, build_minify_sync, build_parse, build_parse_sync, build_print, build_print_sync, + build_transform, build_transform_sync, }; -use wasm_bindgen::{prelude::*, JsCast}; +use wasm_bindgen::prelude::*; 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)] @@ -68,210 +44,11 @@ export function transform( export function transformSync(code: string | Program, opts?: Options, experimental_plugin_bytes_resolver?: any): Output; "#; -fn try_with_handler(cm: Lrc, config: HandlerOpts, op: F) -> Result -where - F: FnOnce(&Handler) -> Result, -{ - GLOBALS.set(&Default::default(), || { - swc_core::base::try_with_handler(cm, config, op) - }) -} - -#[wasm_bindgen( - js_name = "minifySync", - typescript_type = "minifySync", - skip_typescript -)] -pub fn minify_sync(s: JsString, opts: JsValue) -> Result { - let c = compiler(); - try_with_handler(c.cm.clone(), Default::default(), |handler| { - c.run(|| { - let opts = if opts.is_null() || opts.is_undefined() { - Default::default() - } else { - 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")?; - - program - .serialize(&COMPAT_SERIALIZER) - .map_err(|e| anyhow::anyhow!("failed to serialize program: {}", e)) - }) - }) - .map_err(|e| convert_err(e, None)) -} - -#[wasm_bindgen(js_name = "minify", typescript_type = "minify", skip_typescript)] -pub fn minify(s: JsString, opts: JsValue) -> Promise { - future_to_promise(async { minify_sync(s, opts) }) -} - -#[wasm_bindgen(js_name = "parseSync", typescript_type = "parseSync", skip_typescript)] -pub fn parse_sync(s: JsString, opts: JsValue) -> Result { - let c = compiler(); - try_with_handler(c.cm.clone(), Default::default(), |handler| { - c.run(|| { - GLOBALS.set(&Default::default(), || { - let opts: ParseOptions = if opts.is_null() || opts.is_undefined() { - Default::default() - } else { - 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(); - let comments = if opts.comments { - Some(&cmts as &dyn comments::Comments) - } else { - None - }; - let mut program = anyhow::Context::context( - c.parse_js( - fm, - handler, - opts.target, - opts.syntax, - opts.is_module, - comments, - ), - "failed to parse code", - )?; - - program.visit_mut_with(&mut resolver( - Mark::new(), - Mark::new(), - opts.syntax.typescript(), - )); - - program - .serialize(&COMPAT_SERIALIZER) - .map_err(|e| anyhow::anyhow!("failed to serialize program: {}", e)) - }) - }) - }) - .map_err(|e| convert_err(e, None)) -} - -#[wasm_bindgen(js_name = "parse", typescript_type = "parse", skip_typescript)] -pub fn parse(s: JsString, opts: JsValue) -> Promise { - future_to_promise(async { parse_sync(s, opts) }) -} - -#[wasm_bindgen( - js_name = "transformSync", - typescript_type = "transformSync", - skip_typescript -)] -#[allow(unused_variables)] -pub fn transform_sync( - s: JsValue, - opts: JsValue, - experimental_plugin_bytes_resolver: JsValue, -) -> Result { - let c = compiler(); - let opts: Options = if opts.is_null() || opts.is_undefined() { - Default::default() - } else { - 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(|| { - let s = JsCast::dyn_into::(s); - let out = match s { - Ok(s) => { - let fm = c.cm.new_source_file( - if opts.filename.is_empty() { - FileName::Anon - } else { - FileName::Real(opts.filename.clone().into()) - }, - s.into(), - ); - let cm = c.cm.clone(); - let file = fm.clone(); - let comments = SingleThreadedComments::default(); - anyhow::Context::context( - c.process_js_with_custom_pass( - fm, - None, - handler, - &opts, - comments, - |_| noop(), - |_| noop(), - ), - "failed to process js file", - )? - } - Err(v) => { - c.process_js(handler, serde_wasm_bindgen::from_value(v).expect("Should able to deserialize into program"), &opts)? - } - }; - - out.serialize(&COMPAT_SERIALIZER) - .map_err(|e| anyhow::anyhow!("failed to serialize transform result: {}", e)) - }) - }) - .map_err(|e| convert_err(e, Some(error_format))) -} - -#[wasm_bindgen(js_name = "transform", typescript_type = "transform", skip_typescript)] -pub fn transform( - s: JsValue, - opts: JsValue, - experimental_plugin_bytes_resolver: JsValue, -) -> Promise { - future_to_promise(async { transform_sync(s, opts, experimental_plugin_bytes_resolver) }) -} - -#[wasm_bindgen(js_name = "printSync", typescript_type = "printSync", skip_typescript)] -pub fn print_sync(s: JsValue, opts: JsValue) -> Result { - let c = compiler(); - try_with_handler(c.cm.clone(), Default::default(), |_handler| { - c.run(|| { - let opts: Options = if opts.is_null() || opts.is_undefined() { - Default::default() - } else { - serde_wasm_bindgen::from_value(opts) - .map_err(|e| anyhow::anyhow!("failed to parse options: {}", e))? - }; - - 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, - None, - None, - true, - opts.codegen_target().unwrap_or(EsVersion::Es2020), - opts.source_maps - .clone() - .unwrap_or(SourceMapsConfig::Bool(false)), - &Default::default(), - None, - opts.config.minify.into(), - None, - opts.config.emit_source_map_columns.into_bool(), - false, - ), - "failed to print code", - )?; - - serde_wasm_bindgen::to_value(&s) - .map_err(|e| anyhow::anyhow!("failed to serialize json: {}", e)) - }) - }) - .map_err(|e| convert_err(e, None)) -} - -#[wasm_bindgen(js_name = "print", typescript_type = "print", skip_typescript)] -pub fn print(s: JsValue, opts: JsValue) -> Promise { - future_to_promise(async { print_sync(s, opts) }) -} +build_minify_sync!(#[wasm_bindgen(js_name = "minifySync", typescript_type = "minifySync",skip_typescript)]); +build_minify!(#[wasm_bindgen(js_name = "minify", typescript_type = "minify",skip_typescript)]); +build_parse_sync!(#[wasm_bindgen(js_name = "parseSync", typescript_type = "parseSync",skip_typescript)]); +build_parse!(#[wasm_bindgen(js_name = "parse", typescript_type = "parse",skip_typescript)]); +build_print_sync!(#[wasm_bindgen(js_name = "printSync", typescript_type = "printSync",skip_typescript)]); +build_print!(#[wasm_bindgen(js_name = "print", typescript_type = "print",skip_typescript)]); +build_transform_sync!(#[wasm_bindgen(js_name = "transformSync", typescript_type = "transformSync",skip_typescript)]); +build_transform!(#[wasm_bindgen(js_name = "transform", typescript_type = "transform",skip_typescript)]); diff --git a/bindings/binding_core_wasm/src/types.rs b/bindings/binding_core_wasm/src/types.rs index 17a01eed21c6..7f0e20ad90d7 100644 --- a/bindings/binding_core_wasm/src/types.rs +++ b/bindings/binding_core_wasm/src/types.rs @@ -364,11 +364,11 @@ export interface TerserCompressOptions { export interface TerserMangleOptions { props?: TerserManglePropertiesOptions, - top_level?: boolean, + toplevel?: boolean, - keep_class_names?: boolean, + keep_classnames?: boolean, - keep_fn_names?: boolean, + keep_fnames?: boolean, keep_private_props?: boolean, @@ -678,7 +678,7 @@ export interface JscConfig { baseUrl?: string paths?: { - [from: string]: [string] + [from: string]: string[] } minify?: JsMinifyOptions; @@ -907,7 +907,7 @@ export interface GlobalPassOption { envs?: string[]; } -export type ModuleConfig = Es6Config | CommonJsConfig | UmdConfig | AmdConfig | NodeNextConfig; +export type ModuleConfig = Es6Config | CommonJsConfig | UmdConfig | AmdConfig | NodeNextConfig | SystemjsConfig; export interface BaseModuleConfig { /** @@ -1068,6 +1068,8 @@ export interface BaseModuleConfig { * If set to true, dynamic imports will be preserved. */ ignoreDynamic?: boolean; + allowTopLevelThis?: boolean; + preserveImportMeta?: boolean; } export interface Es6Config extends BaseModuleConfig { @@ -1091,7 +1093,10 @@ export interface AmdConfig extends BaseModuleConfig { type: "amd"; moduleId?: string; } - +export interface SystemjsConfig { + type: "systemjs"; + allowTopLevelThis?: boolean; +} export interface Output { /** * Transformed code