refactor(wasm): add source_type for parser, replace class options with plain object (#5217)

- Feat: add `source_type` to `ParserOptions`
- Refactor: use plain objects for options instead of `new
OxcRunOptions()` and `new OxcParserOptions()`, allowing easier
serialization.
This commit is contained in:
Kevin Deng 三咲智子 2024-08-26 15:08:35 +08:00 committed by GitHub
parent b4fc521087
commit b39c0d6122
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 112 additions and 329 deletions

View file

@ -149,13 +149,18 @@ impl Oxc {
#[wasm_bindgen] #[wasm_bindgen]
pub fn run( pub fn run(
&mut self, &mut self,
run_options: &OxcRunOptions, run_options: Option<OxcRunOptions>,
parser_options: &OxcParserOptions, parser_options: Option<OxcParserOptions>,
_linter_options: &OxcLinterOptions, linter_options: Option<OxcLinterOptions>,
_codegen_options: &OxcCodegenOptions, codegen_options: Option<OxcCodegenOptions>,
minifier_options: &OxcMinifierOptions, minifier_options: Option<OxcMinifierOptions>,
) -> Result<(), serde_wasm_bindgen::Error> { ) -> Result<(), serde_wasm_bindgen::Error> {
self.diagnostics = RefCell::default(); self.diagnostics = RefCell::default();
let run_options = run_options.unwrap_or_default();
let parser_options = parser_options.unwrap_or_default();
let _linter_options = linter_options.unwrap_or_default();
let _codegen_options = codegen_options.unwrap_or_default();
let minifier_options = minifier_options.unwrap_or_default();
let allocator = Allocator::default(); let allocator = Allocator::default();
let source_text = &self.source_text; let source_text = &self.source_text;
@ -163,10 +168,17 @@ impl Oxc {
parser_options.source_filename.clone().unwrap_or_else(|| "test.tsx".to_string()), parser_options.source_filename.clone().unwrap_or_else(|| "test.tsx".to_string()),
); );
let source_type = SourceType::from_path(&path).unwrap_or_default(); let source_type = SourceType::from_path(&path).unwrap_or_default();
let source_type = match parser_options.source_type.as_deref() {
Some("script") => source_type.with_script(true),
Some("module") => source_type.with_module(true),
_ => source_type,
};
let ret = Parser::new(&allocator, source_text, source_type) let ret = Parser::new(&allocator, source_text, source_type)
.with_options(ParseOptions { .with_options(ParseOptions {
allow_return_outside_function: parser_options.allow_return_outside_function, allow_return_outside_function: parser_options
.allow_return_outside_function
.unwrap_or_default(),
..ParseOptions::default() ..ParseOptions::default()
}) })
.parse(); .parse();
@ -185,7 +197,7 @@ impl Oxc {
.with_check_syntax_error(true) .with_check_syntax_error(true)
.build(program); .build(program);
if run_options.syntax() { if run_options.syntax.unwrap_or_default() {
self.save_diagnostics( self.save_diagnostics(
semantic_ret.errors.into_iter().map(Error::from).collect::<Vec<_>>(), semantic_ret.errors.into_iter().map(Error::from).collect::<Vec<_>>(),
); );
@ -193,7 +205,7 @@ impl Oxc {
let semantic = Rc::new(semantic_ret.semantic); let semantic = Rc::new(semantic_ret.semantic);
// Only lint if there are not syntax errors // Only lint if there are not syntax errors
if run_options.lint() && self.diagnostics.borrow().is_empty() { if run_options.lint.unwrap_or_default() && self.diagnostics.borrow().is_empty() {
let linter_ret = Linter::default().run(&path, Rc::clone(&semantic)); let linter_ret = Linter::default().run(&path, Rc::clone(&semantic));
let diagnostics = linter_ret.into_iter().map(|e| Error::from(e.error)).collect(); let diagnostics = linter_ret.into_iter().map(|e| Error::from(e.error)).collect();
self.save_diagnostics(diagnostics); self.save_diagnostics(diagnostics);
@ -201,10 +213,12 @@ impl Oxc {
self.ast = program.serialize(&self.serializer)?; self.ast = program.serialize(&self.serializer)?;
if run_options.prettier_format() { if run_options.prettier_format.unwrap_or_default() {
let ret = Parser::new(&allocator, source_text, source_type) let ret = Parser::new(&allocator, source_text, source_type)
.with_options(ParseOptions { .with_options(ParseOptions {
allow_return_outside_function: parser_options.allow_return_outside_function, allow_return_outside_function: parser_options
.allow_return_outside_function
.unwrap_or_default(),
..ParseOptions::default() ..ParseOptions::default()
}) })
.parse(); .parse();
@ -214,10 +228,12 @@ impl Oxc {
self.prettier_formatted_text = printed; self.prettier_formatted_text = printed;
} }
if run_options.prettier_ir() { if run_options.prettier_ir.unwrap_or_default() {
let ret = Parser::new(&allocator, source_text, source_type) let ret = Parser::new(&allocator, source_text, source_type)
.with_options(ParseOptions { .with_options(ParseOptions {
allow_return_outside_function: parser_options.allow_return_outside_function, allow_return_outside_function: parser_options
.allow_return_outside_function
.unwrap_or_default(),
..ParseOptions::default() ..ParseOptions::default()
}) })
.parse(); .parse();
@ -236,7 +252,7 @@ impl Oxc {
}; };
} }
if run_options.transform() { if run_options.transform.unwrap_or_default() {
let (symbols, scopes) = SemanticBuilder::new(source_text, source_type) let (symbols, scopes) = SemanticBuilder::new(source_text, source_type)
.build(program) .build(program)
.semantic .semantic
@ -257,33 +273,35 @@ impl Oxc {
} }
} }
if run_options.scope() || run_options.symbol() { if run_options.scope.unwrap_or_default() || run_options.symbol.unwrap_or_default() {
let semantic = SemanticBuilder::new(source_text, source_type) let semantic = SemanticBuilder::new(source_text, source_type)
.build_module_record(PathBuf::new(), program) .build_module_record(PathBuf::new(), program)
.build(program) .build(program)
.semantic; .semantic;
if run_options.scope() { if run_options.scope.unwrap_or_default() {
self.scope_text = Self::get_scope_text(&semantic); self.scope_text = Self::get_scope_text(&semantic);
} else if run_options.symbol() { } else if run_options.symbol.unwrap_or_default() {
self.symbols = semantic.symbols().serialize(&self.serializer)?; self.symbols = semantic.symbols().serialize(&self.serializer)?;
} }
} }
let program = allocator.alloc(program); let program = allocator.alloc(program);
if minifier_options.compress() || minifier_options.mangle() { if minifier_options.compress.unwrap_or_default()
let compress_options = minifier_options.compress_options(); || minifier_options.mangle.unwrap_or_default()
{
let compress_options = minifier_options.compress_options.unwrap_or_default();
let options = MinifierOptions { let options = MinifierOptions {
mangle: minifier_options.mangle(), mangle: minifier_options.mangle.unwrap_or_default(),
compress: if minifier_options.compress() { compress: if minifier_options.compress.unwrap_or_default() {
CompressOptions { CompressOptions {
booleans: compress_options.booleans(), booleans: compress_options.booleans,
drop_console: compress_options.drop_console(), drop_console: compress_options.drop_console,
drop_debugger: compress_options.drop_debugger(), drop_debugger: compress_options.drop_debugger,
evaluate: compress_options.evaluate(), evaluate: compress_options.evaluate,
join_vars: compress_options.join_vars(), join_vars: compress_options.join_vars,
loops: compress_options.loops(), loops: compress_options.loops,
typeofs: compress_options.typeofs(), typeofs: compress_options.typeofs,
..CompressOptions::default() ..CompressOptions::default()
} }
} else { } else {
@ -295,7 +313,7 @@ impl Oxc {
self.codegen_text = CodeGenerator::new() self.codegen_text = CodeGenerator::new()
.with_options(CodegenOptions { .with_options(CodegenOptions {
minify: minifier_options.whitespace(), minify: minifier_options.whitespace.unwrap_or_default(),
..CodegenOptions::default() ..CodegenOptions::default()
}) })
.build(program) .build(program)

View file

@ -1,233 +1,84 @@
use serde::Deserialize;
use tsify::Tsify; use tsify::Tsify;
use wasm_bindgen::prelude::*; use wasm_bindgen::prelude::*;
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
#[derive(Default, Clone, Copy, Tsify)] #[tsify(from_wasm_abi)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct OxcRunOptions { pub struct OxcRunOptions {
syntax: bool, #[tsify(optional)]
lint: bool, pub syntax: Option<bool>,
format: bool, #[tsify(optional)]
prettier_format: bool, pub lint: Option<bool>,
prettier_ir: bool, #[tsify(optional)]
transform: bool, pub format: Option<bool>,
type_check: bool, #[tsify(optional)]
scope: bool, pub prettier_format: Option<bool>,
symbol: bool, #[tsify(optional)]
pub prettier_ir: Option<bool>,
#[tsify(optional)]
pub transform: Option<bool>,
#[tsify(optional)]
pub type_check: Option<bool>,
#[tsify(optional)]
pub scope: Option<bool>,
#[tsify(optional)]
pub symbol: Option<bool>,
} }
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
impl OxcRunOptions { #[tsify(from_wasm_abi)]
#[wasm_bindgen(constructor)] #[serde(rename_all = "camelCase")]
pub fn new() -> Self {
Self { syntax: true, lint: true, ..Self::default() }
}
#[wasm_bindgen(getter)]
pub fn syntax(&self) -> bool {
self.syntax
}
#[wasm_bindgen(setter)]
pub fn set_syntax(&mut self, yes: bool) {
self.syntax = yes;
}
#[wasm_bindgen(getter)]
pub fn lint(&self) -> bool {
self.lint
}
#[wasm_bindgen(setter)]
pub fn set_lint(&mut self, yes: bool) {
self.lint = yes;
}
#[wasm_bindgen(getter)]
pub fn format(&self) -> bool {
self.format
}
#[wasm_bindgen(setter)]
pub fn set_format(&mut self, yes: bool) {
self.format = yes;
}
#[wasm_bindgen(getter = "prettierFormat")]
pub fn prettier_format(&self) -> bool {
self.prettier_format
}
#[wasm_bindgen(setter = "prettierFormat")]
pub fn set_prettier_format(&mut self, yes: bool) {
self.prettier_format = yes;
}
#[wasm_bindgen(getter = "prettierIr")]
pub fn prettier_ir(&self) -> bool {
self.prettier_ir
}
#[wasm_bindgen(setter = "prettierIr")]
pub fn set_prettier_ir(&mut self, yes: bool) {
self.prettier_ir = yes;
}
#[wasm_bindgen(getter)]
pub fn transform(&self) -> bool {
self.transform
}
#[wasm_bindgen(setter)]
pub fn set_transform(&mut self, yes: bool) {
self.transform = yes;
}
#[wasm_bindgen(getter = "typeCheck")]
pub fn type_check(&self) -> bool {
self.type_check
}
#[wasm_bindgen(setter = "typeCheck")]
pub fn set_type_check(&mut self, yes: bool) {
self.type_check = yes;
}
#[wasm_bindgen(getter)]
pub fn scope(&self) -> bool {
self.scope
}
#[wasm_bindgen(setter)]
pub fn set_scope(&mut self, yes: bool) {
self.scope = yes;
}
#[wasm_bindgen(getter)]
pub fn symbol(&self) -> bool {
self.symbol
}
#[wasm_bindgen(setter)]
pub fn set_symbol(&mut self, yes: bool) {
self.symbol = yes;
}
}
#[wasm_bindgen(getter_with_clone)]
#[derive(Default, Clone)]
pub struct OxcParserOptions { pub struct OxcParserOptions {
#[wasm_bindgen(js_name = allowReturnOutsideFunction)] #[tsify(optional)]
pub allow_return_outside_function: bool, pub allow_return_outside_function: Option<bool>,
#[tsify(optional, type = "\"script\" | \"module\"")]
#[wasm_bindgen(js_name = sourceFilename)] pub source_type: Option<String>,
#[tsify(optional)]
pub source_filename: Option<String>, pub source_filename: Option<String>,
} }
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
impl OxcParserOptions { #[tsify(from_wasm_abi)]
#[wasm_bindgen(constructor)] #[serde(rename_all = "camelCase")]
pub fn new() -> Self { // allow empty object for future compatibility
Self::default() #[allow(clippy::empty_structs_with_brackets)]
} pub struct OxcLinterOptions {}
}
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
#[derive(Default, Clone, Copy)] #[tsify(from_wasm_abi)]
pub struct OxcLinterOptions; #[serde(rename_all = "camelCase")]
#[wasm_bindgen]
impl OxcLinterOptions {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self
}
}
#[wasm_bindgen]
#[derive(Default, Clone, Copy)]
pub struct OxcCodegenOptions { pub struct OxcCodegenOptions {
pub indentation: u8, #[tsify(optional)]
#[wasm_bindgen(js_name = enableTypescript)] pub indentation: Option<u8>,
pub enable_typescript: bool, #[tsify(optional)]
pub enable_typescript: Option<bool>,
} }
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
impl OxcCodegenOptions { #[tsify(from_wasm_abi)]
#[wasm_bindgen(constructor)] #[serde(rename_all = "camelCase")]
pub fn new() -> Self {
Self::default()
}
}
#[wasm_bindgen]
#[derive(Default, Clone, Copy)]
pub struct OxcMinifierOptions { pub struct OxcMinifierOptions {
whitespace: bool, #[tsify(optional)]
mangle: bool, pub whitespace: Option<bool>,
compress: bool, #[tsify(optional)]
compress_options: OxcCompressOptions, pub mangle: Option<bool>,
#[tsify(optional)]
pub compress: Option<bool>,
#[tsify(optional)]
pub compress_options: Option<OxcCompressOptions>,
} }
#[wasm_bindgen] #[derive(Debug, Clone, Deserialize, Tsify)]
#[allow(clippy::trivially_copy_pass_by_ref)] #[tsify(from_wasm_abi)]
impl OxcMinifierOptions {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self::default()
}
#[wasm_bindgen(getter)]
pub fn whitespace(&self) -> bool {
self.whitespace
}
#[wasm_bindgen(setter)]
pub fn set_whitespace(&mut self, yes: bool) {
self.whitespace = yes;
}
#[wasm_bindgen(getter)]
pub fn mangle(&self) -> bool {
self.mangle
}
#[wasm_bindgen(setter)]
pub fn set_mangle(&mut self, yes: bool) {
self.mangle = yes;
}
#[wasm_bindgen(getter)]
pub fn compress(&self) -> bool {
self.compress
}
#[wasm_bindgen(setter)]
pub fn set_compress(&mut self, yes: bool) {
self.compress = yes;
}
#[wasm_bindgen(getter = compressOptions)]
pub fn compress_options(&self) -> OxcCompressOptions {
self.compress_options
}
#[wasm_bindgen(setter = compressOptions)]
pub fn set_compress_options(&mut self, options: OxcCompressOptions) {
self.compress_options = options;
}
}
#[wasm_bindgen]
#[derive(Clone, Copy)]
pub struct OxcCompressOptions { pub struct OxcCompressOptions {
booleans: bool, pub booleans: bool,
drop_debugger: bool, pub drop_debugger: bool,
drop_console: bool, pub drop_console: bool,
evaluate: bool, pub evaluate: bool,
join_vars: bool, pub join_vars: bool,
loops: bool, pub loops: bool,
typeofs: bool, pub typeofs: bool,
} }
// keep same with `oxc_minifier::options::CompressOptions` // keep same with `oxc_minifier::options::CompressOptions`
@ -245,92 +96,7 @@ impl Default for OxcCompressOptions {
} }
} }
#[wasm_bindgen] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
impl OxcCompressOptions { #[tsify(from_wasm_abi)]
#[wasm_bindgen(constructor)] #[serde(rename_all = "camelCase")]
pub fn new() -> Self {
Self::default()
}
#[wasm_bindgen(getter)]
pub fn booleans(self) -> bool {
self.booleans
}
#[wasm_bindgen(setter)]
pub fn set_booleans(&mut self, yes: bool) {
self.booleans = yes;
}
#[wasm_bindgen(getter = dropDebugger)]
pub fn drop_debugger(self) -> bool {
self.drop_debugger
}
#[wasm_bindgen(setter = dropDebugger)]
pub fn set_drop_debugger(&mut self, yes: bool) {
self.drop_debugger = yes;
}
#[wasm_bindgen(getter = dropConsole)]
pub fn drop_console(self) -> bool {
self.drop_console
}
#[wasm_bindgen(setter = dropConsole)]
pub fn set_drop_console(&mut self, yes: bool) {
self.drop_console = yes;
}
#[wasm_bindgen(getter)]
pub fn evaluate(self) -> bool {
self.evaluate
}
#[wasm_bindgen(setter)]
pub fn set_evaluate(&mut self, yes: bool) {
self.evaluate = yes;
}
#[wasm_bindgen(getter = joinVars)]
pub fn join_vars(self) -> bool {
self.join_vars
}
#[wasm_bindgen(setter = joinVars)]
pub fn set_join_vars(&mut self, yes: bool) {
self.join_vars = yes;
}
#[wasm_bindgen(getter)]
pub fn loops(self) -> bool {
self.loops
}
#[wasm_bindgen(setter)]
pub fn set_loops(&mut self, yes: bool) {
self.loops = yes;
}
#[wasm_bindgen(getter)]
pub fn typeofs(self) -> bool {
self.typeofs
}
#[wasm_bindgen(setter)]
pub fn set_typeofs(&mut self, yes: bool) {
self.typeofs = yes;
}
}
#[wasm_bindgen]
#[derive(Default, Clone, Copy)]
pub struct OxcTypeCheckingOptions; pub struct OxcTypeCheckingOptions;
#[wasm_bindgen]
impl OxcTypeCheckingOptions {
#[wasm_bindgen(constructor)]
pub fn new() -> Self {
Self
}
}

View file

@ -9,13 +9,12 @@ use wasm_bindgen::prelude::*;
#[derive(Debug, Default, Clone, Deserialize, Tsify)] #[derive(Debug, Default, Clone, Deserialize, Tsify)]
#[tsify(from_wasm_abi)] #[tsify(from_wasm_abi)]
#[serde(rename_all = "camelCase")]
pub struct ParserOptions { pub struct ParserOptions {
#[serde(rename = "sourceType")]
#[tsify(optional, type = "\"script\" | \"module\"")] #[tsify(optional, type = "\"script\" | \"module\"")]
pub source_type: Option<String>, pub source_type: Option<String>,
/// "module" and "jsx" will be inferred from `sourceFilename`. /// "module" and "jsx" will be inferred from `sourceFilename`.
#[serde(rename = "sourceFilename")]
#[tsify(optional)] #[tsify(optional)]
pub source_filename: Option<String>, pub source_filename: Option<String>,
} }