diff --git a/Cargo.lock b/Cargo.lock index 4e831176de0d1..146c70d22d85a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1601,6 +1601,7 @@ dependencies = [ "oxc_parser", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "rustc-hash", ] @@ -1711,6 +1712,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "oxc_traverse", "pico-args", ] @@ -1752,6 +1754,7 @@ dependencies = [ "oxc_ast", "oxc_parser", "oxc_span", + "oxc_syntax_operations", ] [[package]] @@ -1770,6 +1773,7 @@ dependencies = [ "oxc_regular_expression", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "pico-args", "rustc-hash", "seq-macro", @@ -1883,6 +1887,7 @@ dependencies = [ "oxc_parser", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "phf 0.11.2", "rustc-hash", "serde", @@ -1939,6 +1944,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" @@ -2000,6 +2013,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "oxc_traverse", "pico-args", "ropey", @@ -2021,6 +2035,7 @@ dependencies = [ "oxc_semantic", "oxc_span", "oxc_syntax", + "oxc_syntax_operations", "rustc-hash", ] diff --git a/Cargo.toml b/Cargo.toml index 65cd9f4947305..191efd03ff4dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -94,6 +94,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 611449bc6b7bb..1d7de69e2e82c 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 ada15a0f2b37c..bd6517567fee3 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 99% rename from crates/oxc_ast/src/syntax_directed_operations/bound_names.rs rename to crates/oxc_syntax_operations/src/bound_names.rs index ce9ca5d413eb8..975b29e7b7d7a 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs +++ b/crates/oxc_syntax_operations/src/bound_names.rs @@ -1,4 +1,4 @@ -use crate::ast::*; +use oxc_ast::ast::*; /// [`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 95% 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..21822c1f5a778 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::*; /// [`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 98% 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..e72586ff191ec 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,4 @@ -use crate::ast::*; +use oxc_ast::ast::*; /// [`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 98% rename from crates/oxc_ast/src/syntax_directed_operations/prop_name.rs rename to crates/oxc_syntax_operations/src/prop_name.rs index 0b56af7261372..810c341073e50 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/prop_name.rs +++ b/crates/oxc_syntax_operations/src/prop_name.rs @@ -1,7 +1,6 @@ +use oxc_ast::ast::*; 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 fb86c6971aed5..d4cf7f1971565 100644 --- a/crates/oxc_transformer/Cargo.toml +++ b/crates/oxc_transformer/Cargo.toml @@ -29,6 +29,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 } assert-unchecked = { workspace = true } diff --git a/crates/oxc_transformer/src/react/jsx.rs b/crates/oxc_transformer/src/react/jsx.rs index 15531e910e7b5..c960b47384de5 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::{Traverse, TraverseCtx}; use super::diagnostics; diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index 8ea935bb598a2..027d7296f7024 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 254834e69c7ad..2a50dd939f5a4 100644 --- a/crates/oxc_traverse/Cargo.toml +++ b/crates/oxc_traverse/Cargo.toml @@ -28,6 +28,7 @@ oxc_ast = { 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/context/ast_operations/gather_node_parts.rs b/crates/oxc_traverse/src/context/ast_operations/gather_node_parts.rs index bf528effbb126..93c3f3a7621c7 100644 --- a/crates/oxc_traverse/src/context/ast_operations/gather_node_parts.rs +++ b/crates/oxc_traverse/src/context/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; pub trait GatherNodeParts<'a> { fn gather(&self, f: &mut F);