diff --git a/Cargo.lock b/Cargo.lock index 7ba040abcccfb..40ea6409967bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1612,6 +1612,7 @@ dependencies = [ "oxc_parser", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "rustc-hash", ] @@ -1722,6 +1723,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "oxc_traverse", "pico-args", ] @@ -1763,6 +1765,7 @@ dependencies = [ "oxc_ast", "oxc_parser", "oxc_span", + "oxc_syntax_operations", ] [[package]] @@ -1781,6 +1784,7 @@ dependencies = [ "oxc_regular_expression", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "pico-args", "rustc-hash", "seq-macro", @@ -1890,6 +1894,7 @@ dependencies = [ "oxc_parser", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "phf 0.11.2", "rustc-hash", "serde", @@ -1946,6 +1951,14 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "oxc_syntax_operations" +version = "0.30.5" +dependencies = [ + "oxc_ast", + "oxc_span", +] + [[package]] name = "oxc_tasks_common" version = "0.0.0" @@ -2013,6 +2026,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "oxc_traverse", "pico-args", "ropey", @@ -2035,6 +2049,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "rustc-hash", ] diff --git a/Cargo.toml b/Cargo.toml index a6f1a6c55a89c..85226f7621da3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,6 +95,7 @@ oxc_semantic = { version = "0.30.5", path = "crates/oxc_semantic" } oxc_sourcemap = { version = "0.30.5", path = "crates/oxc_sourcemap" } oxc_span = { version = "0.30.5", path = "crates/oxc_span" } oxc_syntax = { version = "0.30.5", path = "crates/oxc_syntax" } +oxc_syntax_operations = { version = "0.30.5", path = "crates/oxc_syntax_operations" } oxc_transform_napi = { version = "0.30.5", path = "napi/transform" } oxc_transformer = { version = "0.30.5", path = "crates/oxc_transformer" } oxc_traverse = { version = "0.30.5", path = "crates/oxc_traverse" } diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 5b93a1fda3080..c11746f21b938 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -382,14 +382,6 @@ impl<'a> ArrayExpressionElement<'a> { } } -impl<'a> ObjectExpression<'a> { - /// Returns `true` if this object has a property named `__proto__` - pub fn has_proto(&self) -> bool { - use crate::syntax_directed_operations::PropName; - self.properties.iter().any(|p| p.prop_name().is_some_and(|name| name.0 == "__proto__")) - } -} - impl<'a> PropertyKey<'a> { pub fn static_name(&self) -> Option> { match self { diff --git a/crates/oxc_ast/src/lib.rs b/crates/oxc_ast/src/lib.rs index 006fa94352287..2a99c0960347f 100644 --- a/crates/oxc_ast/src/lib.rs +++ b/crates/oxc_ast/src/lib.rs @@ -33,7 +33,6 @@ mod ast_builder_impl; mod ast_impl; mod ast_kind_impl; pub mod precedence; -pub mod syntax_directed_operations; mod trivia; mod generated { diff --git a/crates/oxc_ast/src/syntax_directed_operations/mod.rs b/crates/oxc_ast/src/syntax_directed_operations/mod.rs deleted file mode 100644 index f44cc8bd4958a..0000000000000 --- a/crates/oxc_ast/src/syntax_directed_operations/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -//! [ECMA262 Syntax-Directed Operations](https://tc39.es/ecma262/#sec-syntax-directed-operations) - -mod bound_names; -mod is_simple_parameter_list; -mod private_bound_identifiers; -mod prop_name; - -pub use self::{ - bound_names::BoundNames, is_simple_parameter_list::IsSimpleParameterList, - private_bound_identifiers::PrivateBoundIdentifiers, prop_name::PropName, -}; diff --git a/crates/oxc_isolated_declarations/Cargo.toml b/crates/oxc_isolated_declarations/Cargo.toml index 0309938fc1c40..62ec31d30bcfd 100644 --- a/crates/oxc_isolated_declarations/Cargo.toml +++ b/crates/oxc_isolated_declarations/Cargo.toml @@ -29,6 +29,7 @@ oxc_ast = { workspace = true } oxc_diagnostics = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true, features = ["to_js_string"] } +oxc_syntax_operations = { workspace = true } bitflags = { workspace = true } rustc-hash = { workspace = true } diff --git a/crates/oxc_isolated_declarations/src/declaration.rs b/crates/oxc_isolated_declarations/src/declaration.rs index e0c29c9d141ff..8d616f440c339 100644 --- a/crates/oxc_isolated_declarations/src/declaration.rs +++ b/crates/oxc_isolated_declarations/src/declaration.rs @@ -6,9 +6,10 @@ use oxc_allocator::Vec; #[allow(clippy::wildcard_imports)] use oxc_ast::ast::*; use oxc_ast::visit::walk_mut::walk_ts_signatures; -use oxc_ast::{syntax_directed_operations::BoundNames, Visit, VisitMut}; +use oxc_ast::{Visit, VisitMut}; use oxc_span::{GetSpan, SPAN}; use oxc_syntax::scope::ScopeFlags; +use oxc_syntax_operations::BoundNames; use crate::diagnostics::accessor_must_have_explicit_return_type; use crate::{ diff --git a/crates/oxc_minifier/Cargo.toml b/crates/oxc_minifier/Cargo.toml index a868ebaf4c7ee..5bc22a0cbab2b 100644 --- a/crates/oxc_minifier/Cargo.toml +++ b/crates/oxc_minifier/Cargo.toml @@ -29,6 +29,7 @@ oxc_parser = { workspace = true } oxc_semantic = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true } +oxc_syntax_operations = { workspace = true } oxc_traverse = { workspace = true } cow-utils = { workspace = true } diff --git a/crates/oxc_minifier/src/keep_var.rs b/crates/oxc_minifier/src/keep_var.rs index e7749733821ea..782564d77f3e7 100644 --- a/crates/oxc_minifier/src/keep_var.rs +++ b/crates/oxc_minifier/src/keep_var.rs @@ -1,5 +1,6 @@ -use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, AstBuilder, Visit, NONE}; +use oxc_ast::{ast::*, AstBuilder, Visit, NONE}; use oxc_span::{Atom, Span, SPAN}; +use oxc_syntax_operations::BoundNames; pub struct KeepVar<'a> { ast: AstBuilder<'a>, diff --git a/crates/oxc_module_lexer/Cargo.toml b/crates/oxc_module_lexer/Cargo.toml index b282b697437c3..44566b81cefaf 100644 --- a/crates/oxc_module_lexer/Cargo.toml +++ b/crates/oxc_module_lexer/Cargo.toml @@ -23,6 +23,7 @@ doctest = false [dependencies] oxc_ast = { workspace = true } oxc_span = { workspace = true } +oxc_syntax_operations = { workspace = true } [dev-dependencies] oxc_allocator = { workspace = true } diff --git a/crates/oxc_module_lexer/src/lib.rs b/crates/oxc_module_lexer/src/lib.rs index 650929cb5d70b..ccd422af68f89 100644 --- a/crates/oxc_module_lexer/src/lib.rs +++ b/crates/oxc_module_lexer/src/lib.rs @@ -7,8 +7,9 @@ use oxc_ast::visit::walk::{ walk_import_expression, walk_meta_property, walk_module_declaration, walk_statement, }; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, Visit}; +use oxc_ast::{ast::*, Visit}; use oxc_span::{Atom, GetSpan}; +use oxc_syntax_operations::BoundNames; #[derive(Debug, Clone)] pub struct ImportSpecifier<'a> { diff --git a/crates/oxc_parser/Cargo.toml b/crates/oxc_parser/Cargo.toml index 7562d2f21293c..ecfb16be80acb 100644 --- a/crates/oxc_parser/Cargo.toml +++ b/crates/oxc_parser/Cargo.toml @@ -25,6 +25,7 @@ oxc_diagnostics = { workspace = true } oxc_regular_expression = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true } +oxc_syntax_operations = { workspace = true } assert-unchecked = { workspace = true } bitflags = { workspace = true } diff --git a/crates/oxc_parser/src/js/class.rs b/crates/oxc_parser/src/js/class.rs index 32a7308e2f8cc..e44f0e44a26cc 100644 --- a/crates/oxc_parser/src/js/class.rs +++ b/crates/oxc_parser/src/js/class.rs @@ -1,7 +1,8 @@ use oxc_allocator::{Box, Vec}; -use oxc_ast::{ast::*, syntax_directed_operations::PropName}; +use oxc_ast::ast::*; use oxc_diagnostics::Result; use oxc_span::{GetSpan, Span}; +use oxc_syntax_operations::PropName; use crate::{ diagnostics, diff --git a/crates/oxc_semantic/Cargo.toml b/crates/oxc_semantic/Cargo.toml index 2b6a47f166fc9..51b087b0b22f4 100644 --- a/crates/oxc_semantic/Cargo.toml +++ b/crates/oxc_semantic/Cargo.toml @@ -26,6 +26,7 @@ oxc_diagnostics = { workspace = true } oxc_index = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true } +oxc_syntax_operations = { workspace = true } assert-unchecked = { workspace = true } indexmap = { workspace = true } diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index bdf9bfad16cb3..c43a45767e832 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -3,12 +3,9 @@ use std::{borrow::Cow, ptr}; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ - ast::*, - syntax_directed_operations::{BoundNames, IsSimpleParameterList}, - AstKind, -}; +use oxc_ast::{ast::*, AstKind}; use oxc_span::{GetSpan, SourceType}; +use oxc_syntax_operations::{BoundNames, IsSimpleParameterList}; use crate::{ scope::{ScopeFlags, ScopeId}, diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index 6b6cd35912b5e..6b5374d062562 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -2,11 +2,7 @@ use phf::{phf_set, Set}; use rustc_hash::FxHashMap; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ - ast::*, - syntax_directed_operations::{IsSimpleParameterList, PropName}, - AstKind, -}; +use oxc_ast::{ast::*, AstKind}; use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_span::{GetSpan, ModuleKind, Span}; use oxc_syntax::{ @@ -14,6 +10,7 @@ use oxc_syntax::{ number::NumberBase, operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}, }; +use oxc_syntax_operations::{IsSimpleParameterList, PropName}; use crate::{builder::SemanticBuilder, diagnostics::redeclaration, scope::ScopeFlags, AstNode}; diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index 18cd890307737..86d3547ea90c4 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -3,13 +3,10 @@ use std::borrow::Cow; use rustc_hash::FxHashMap; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ - ast::*, - syntax_directed_operations::{BoundNames, PropName}, - AstKind, -}; +use oxc_ast::{ast::*, AstKind}; use oxc_diagnostics::OxcDiagnostic; use oxc_span::{Atom, GetSpan, Span}; +use oxc_syntax_operations::{BoundNames, PropName}; use crate::{builder::SemanticBuilder, diagnostics::redeclaration}; diff --git a/crates/oxc_semantic/src/module_record/builder.rs b/crates/oxc_semantic/src/module_record/builder.rs index d3e326a0db7e7..bbe1ca0817be4 100644 --- a/crates/oxc_semantic/src/module_record/builder.rs +++ b/crates/oxc_semantic/src/module_record/builder.rs @@ -1,10 +1,11 @@ use std::path::PathBuf; #[allow(clippy::wildcard_imports)] -use oxc_ast::{ast::*, syntax_directed_operations::BoundNames}; +use oxc_ast::ast::*; use oxc_span::{CompactStr, GetSpan, Span}; #[allow(clippy::wildcard_imports)] use oxc_syntax::module_record::*; +use oxc_syntax_operations::BoundNames; #[derive(Default)] pub struct ModuleRecordBuilder { diff --git a/crates/oxc_syntax_operations/Cargo.toml b/crates/oxc_syntax_operations/Cargo.toml new file mode 100644 index 0000000000000..21e781a4c7376 --- /dev/null +++ b/crates/oxc_syntax_operations/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "oxc_syntax_operations" +version = "0.30.5" +authors.workspace = true +categories.workspace = true +edition.workspace = true +homepage.workspace = true +include = ["/src"] +keywords.workspace = true +license.workspace = true +publish = true +repository.workspace = true +rust-version.workspace = true +description.workspace = true + +[lints] +workspace = true + +[lib] +test = false +doctest = false + +[dependencies] +oxc_ast = { workspace = true } +oxc_span = { workspace = true } diff --git a/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs b/crates/oxc_syntax_operations/src/bound_names.rs similarity index 93% rename from crates/oxc_ast/src/syntax_directed_operations/bound_names.rs rename to crates/oxc_syntax_operations/src/bound_names.rs index ce9ca5d413eb8..aebffc84c6c39 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs +++ b/crates/oxc_syntax_operations/src/bound_names.rs @@ -1,4 +1,9 @@ -use crate::ast::*; +use oxc_ast::ast::{ + ArrayPattern, AssignmentPattern, BindingIdentifier, BindingPattern, BindingPatternKind, + BindingRestElement, Class, Declaration, ExportNamedDeclaration, FormalParameter, + FormalParameters, Function, ImportDeclaration, ImportDeclarationSpecifier, ModuleDeclaration, + ObjectPattern, VariableDeclaration, +}; /// [`BoundName`](https://tc39.es/ecma262/#sec-static-semantics-boundnames) pub trait BoundName<'a> { diff --git a/crates/oxc_syntax_operations/src/has_proto.rs b/crates/oxc_syntax_operations/src/has_proto.rs new file mode 100644 index 0000000000000..341d198714eba --- /dev/null +++ b/crates/oxc_syntax_operations/src/has_proto.rs @@ -0,0 +1,14 @@ +use oxc_ast::ast::ObjectExpression; + +use crate::PropName; + +pub trait HasProto { + /// Returns `true` if this object has a property named `__proto__` + fn has_proto(&self) -> bool; +} + +impl<'a> HasProto for ObjectExpression<'a> { + fn has_proto(&self) -> bool { + self.properties.iter().any(|p| p.prop_name().is_some_and(|name| name.0 == "__proto__")) + } +} diff --git a/crates/oxc_ast/src/syntax_directed_operations/is_simple_parameter_list.rs b/crates/oxc_syntax_operations/src/is_simple_parameter_list.rs similarity index 91% rename from crates/oxc_ast/src/syntax_directed_operations/is_simple_parameter_list.rs rename to crates/oxc_syntax_operations/src/is_simple_parameter_list.rs index be773071ffa87..a1369f6bd54a5 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/is_simple_parameter_list.rs +++ b/crates/oxc_syntax_operations/src/is_simple_parameter_list.rs @@ -1,4 +1,4 @@ -use crate::ast::*; +use oxc_ast::ast::FormalParameters; /// [`IsSimpleParameterList`](https://tc39.es/ecma262/#sec-static-semantics-issimpleparameterlist) pub trait IsSimpleParameterList { diff --git a/crates/oxc_syntax_operations/src/lib.rs b/crates/oxc_syntax_operations/src/lib.rs new file mode 100644 index 0000000000000..d3d2bcd2a8370 --- /dev/null +++ b/crates/oxc_syntax_operations/src/lib.rs @@ -0,0 +1,20 @@ +//! Traits for JavaScript syntax operations +//! +//! * BoundNames +//! * IsSimpleParameterList +//! * PrivateBoundIdentifiers +//! * PropName +//! * Constant Folding +//! +//! See [ECMA262 Syntax-Directed Operations](https://tc39.es/ecma262/#sec-syntax-directed-operations) + +mod bound_names; +mod has_proto; +mod is_simple_parameter_list; +mod private_bound_identifiers; +mod prop_name; + +pub use self::{ + bound_names::BoundNames, has_proto::HasProto, is_simple_parameter_list::IsSimpleParameterList, + private_bound_identifiers::PrivateBoundIdentifiers, prop_name::PropName, +}; diff --git a/crates/oxc_ast/src/syntax_directed_operations/private_bound_identifiers.rs b/crates/oxc_syntax_operations/src/private_bound_identifiers.rs similarity index 92% rename from crates/oxc_ast/src/syntax_directed_operations/private_bound_identifiers.rs rename to crates/oxc_syntax_operations/src/private_bound_identifiers.rs index 4c1a1ee026e86..68fe360935908 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/private_bound_identifiers.rs +++ b/crates/oxc_syntax_operations/src/private_bound_identifiers.rs @@ -1,4 +1,7 @@ -use crate::ast::*; +use oxc_ast::ast::{ + AccessorProperty, ClassElement, MethodDefinition, PrivateIdentifier, PropertyDefinition, + PropertyKey, +}; /// [`PrivateBoundIdentifiers`](https://tc39.es/ecma262/#sec-static-semantics-privateboundidentifiers) pub trait PrivateBoundIdentifiers { diff --git a/crates/oxc_ast/src/syntax_directed_operations/prop_name.rs b/crates/oxc_syntax_operations/src/prop_name.rs similarity index 92% rename from crates/oxc_ast/src/syntax_directed_operations/prop_name.rs rename to crates/oxc_syntax_operations/src/prop_name.rs index 0b56af7261372..f72f863bb0442 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/prop_name.rs +++ b/crates/oxc_syntax_operations/src/prop_name.rs @@ -1,7 +1,9 @@ +use oxc_ast::ast::{ + ClassElement, MethodDefinition, ObjectProperty, ObjectPropertyKind, PropertyDefinition, + PropertyKey, PropertyKind, +}; use oxc_span::Span; -use crate::ast::*; - /// [`PropName`](https://tc39.es/ecma262/#sec-static-semantics-propname) pub trait PropName { fn prop_name(&self) -> Option<(&str, Span)>; diff --git a/crates/oxc_transformer/Cargo.toml b/crates/oxc_transformer/Cargo.toml index 8d74b5098d8c5..7486072df3649 100644 --- a/crates/oxc_transformer/Cargo.toml +++ b/crates/oxc_transformer/Cargo.toml @@ -35,6 +35,7 @@ oxc_regular_expression = { workspace = true } oxc_semantic = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true, features = ["to_js_string"] } +oxc_syntax_operations = { workspace = true } oxc_traverse = { workspace = true } ropey = { workspace = true } rustc-hash = { workspace = true } diff --git a/crates/oxc_transformer/src/react/jsx.rs b/crates/oxc_transformer/src/react/jsx.rs index 483cc8bfb7c55..e8c27a3feb9c8 100644 --- a/crates/oxc_transformer/src/react/jsx.rs +++ b/crates/oxc_transformer/src/react/jsx.rs @@ -97,6 +97,7 @@ use oxc_syntax::{ symbol::SymbolFlags, xml_entities::XML_ENTITIES, }; +use oxc_syntax_operations::HasProto; use oxc_traverse::{BoundIdentifier, Traverse, TraverseCtx}; use crate::{common::module_imports::NamedImport, TransformCtx}; diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index bbb1ccaad01fe..7d21a173e06e2 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -1,12 +1,14 @@ use oxc_allocator::{Box, Vec}; -use oxc_ast::{ast::*, syntax_directed_operations::BoundNames, NONE}; +use oxc_ast::{ast::*, NONE}; use oxc_span::{Atom, CompactStr, SPAN}; use oxc_syntax::{ operator::{AssignmentOperator, LogicalOperator}, scope::{ScopeFlags, ScopeId}, symbol::SymbolFlags, }; +use oxc_syntax_operations::BoundNames; use oxc_traverse::{Traverse, TraverseCtx}; + use rustc_hash::FxHashSet; use super::{ diff --git a/crates/oxc_traverse/Cargo.toml b/crates/oxc_traverse/Cargo.toml index 6267f24f73973..d4a28a54173bf 100644 --- a/crates/oxc_traverse/Cargo.toml +++ b/crates/oxc_traverse/Cargo.toml @@ -29,6 +29,7 @@ oxc_data_structures = { workspace = true } oxc_semantic = { workspace = true } oxc_span = { workspace = true } oxc_syntax = { workspace = true } +oxc_syntax_operations = { workspace = true } compact_str = { workspace = true } itoa = { workspace = true } diff --git a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs index 6074b97546a68..b39ce3c72d7ef 100644 --- a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs +++ b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs @@ -6,7 +6,7 @@ #[allow(clippy::wildcard_imports)] use oxc_ast::ast::*; -use oxc_ast::syntax_directed_operations::BoundNames; +use oxc_syntax_operations::BoundNames; use super::to_identifier;