From f131442bbf832e484f279e263b81a4b0dc8e34a6 Mon Sep 17 00:00:00 2001 From: cinchen Date: Tue, 26 Mar 2024 20:05:36 +0800 Subject: [PATCH 1/8] feat(linter): eslint-plugin-jest/no-untyped-mock-factory (#2807) Rule Detail: [link](https://github.com/jest-community/eslint-plugin-jest/blob/main/src/rules/no-untyped-mock-factory.ts) --------- Co-authored-by: wenzhe Co-authored-by: Dunqing --- crates/oxc_linter/src/rules.rs | 2 + .../src/rules/jest/no_untyped_mock_factory.rs | 414 ++++++++++++++++++ .../snapshots/no_untyped_mock_factory.snap | 58 +++ 3 files changed, 474 insertions(+) create mode 100644 crates/oxc_linter/src/rules/jest/no_untyped_mock_factory.rs create mode 100644 crates/oxc_linter/src/snapshots/no_untyped_mock_factory.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 4532baa0c4af5..3f6f297b17da2 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -164,6 +164,7 @@ mod jest { pub mod no_standalone_expect; pub mod no_test_prefixes; pub mod no_test_return_statement; + pub mod no_untyped_mock_factory; pub mod prefer_called_with; pub mod prefer_equality_matcher; pub mod prefer_expect_resolves; @@ -484,6 +485,7 @@ oxc_macros::declare_all_lint_rules! { jest::no_standalone_expect, jest::no_test_prefixes, jest::no_test_return_statement, + jest::no_untyped_mock_factory, jest::prefer_called_with, jest::prefer_equality_matcher, jest::prefer_expect_resolves, diff --git a/crates/oxc_linter/src/rules/jest/no_untyped_mock_factory.rs b/crates/oxc_linter/src/rules/jest/no_untyped_mock_factory.rs new file mode 100644 index 0000000000000..2a730d54b0199 --- /dev/null +++ b/crates/oxc_linter/src/rules/jest/no_untyped_mock_factory.rs @@ -0,0 +1,414 @@ +use crate::{ + context::LintContext, + fixer::Fix, + rule::Rule, + utils::{collect_possible_jest_call_node, PossibleJestNode}, +}; + +use oxc_ast::{ + ast::{Argument, Expression}, + AstKind, +}; +use oxc_diagnostics::{ + miette::{self, Diagnostic}, + thiserror::Error, +}; +use oxc_macros::declare_oxc_lint; +use oxc_span::{CompactStr, Span}; + +#[derive(Debug, Error, Diagnostic)] +#[error("eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter.")] +#[diagnostic( + severity(warning), + help("Add a type parameter to the mock factory such as `typeof import({0:?})`") +)] +struct AddTypeParameterToModuleMockDiagnostic(CompactStr, #[label] pub Span); + +#[derive(Debug, Default, Clone)] +pub struct NoUntypedMockFactory; + +declare_oxc_lint!( + /// ### What it does + /// + /// This rule triggers a warning if `mock()` or `doMock()` is used without a generic + /// type parameter or return type. + /// + /// ### Why is this bad? + /// + /// By default, `jest.mock` and `jest.doMock` allow any type to be returned by a + /// mock factory. A generic type parameter can be used to enforce that the factory + /// returns an object with the same shape as the original module, or some other + /// strict type. Requiring a type makes it easier to use TypeScript to catch changes + /// needed in test mocks when the source module changes. + /// + /// ### Example + /// + /// // invalid + /// ```typescript + /// jest.mock('../moduleName', () => { + /// return jest.fn(() => 42); + /// }); + /// + /// jest.mock('./module', () => ({ + /// ...jest.requireActual('./module'), + /// foo: jest.fn(), + /// })); + /// + /// jest.mock('random-num', () => { + /// return jest.fn(() => 42); + /// }); + /// ``` + /// + /// // valid + /// ```typescript + /// + /// // Uses typeof import() + /// jest.mock('../moduleName', () => { + /// return jest.fn(() => 42); + /// }); + /// + /// jest.mock('./module', () => ({ + /// ...jest.requireActual('./module'), + /// foo: jest.fn(), + /// })); + /// + /// // Uses custom type + /// jest.mock<() => number>('random-num', () => { + /// return jest.fn(() => 42); + /// }); + /// + /// // No factory + /// jest.mock('random-num'); + /// + /// // Virtual mock + /// jest.mock( + /// '../moduleName', + /// () => { + /// return jest.fn(() => 42); + /// }, + /// { virtual: true }, + /// ); + /// ``` + /// + NoUntypedMockFactory, + style, +); + +impl Rule for NoUntypedMockFactory { + fn run_once(&self, ctx: &LintContext<'_>) { + if !ctx.source_type().is_typescript() { + return; + } + + for possible_jest_node in &collect_possible_jest_call_node(ctx) { + Self::run(possible_jest_node, ctx); + } + } +} + +impl NoUntypedMockFactory { + fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) { + let node = possible_jest_node.node; + let AstKind::CallExpression(call_expr) = node.kind() else { + return; + }; + let Expression::MemberExpression(mem_expr) = &call_expr.callee else { + return; + }; + let Some((property_span, property_name)) = mem_expr.static_property_info() else { + return; + }; + + if call_expr.arguments.len() != 2 && (property_name != "mock" || property_name != "doMock") + { + return; + } + + let Some(factory_node) = call_expr.arguments.get(1) else { + return; + }; + + if call_expr.type_parameters.is_some() || Self::has_return_type(factory_node) { + return; + } + + let Some(name_node) = call_expr.arguments.first() else { + return; + }; + let Argument::Expression(expr) = name_node else { + return; + }; + + if let Expression::StringLiteral(string_literal) = expr { + ctx.diagnostic_with_fix( + AddTypeParameterToModuleMockDiagnostic( + string_literal.value.to_compact_str(), + property_span, + ), + || { + let mut content = ctx.codegen(); + content.print_str(b"("); + + Fix::new( + content.into_source_text(), + Span::new(string_literal.span.start - 1, string_literal.span.start), + ) + }, + ); + } else if let Expression::Identifier(ident) = expr { + ctx.diagnostic(AddTypeParameterToModuleMockDiagnostic( + ident.name.to_compact_str(), + property_span, + )); + } + } + + fn has_return_type(argument: &Argument) -> bool { + let Argument::Expression(expr) = argument else { + return false; + }; + + match expr { + Expression::FunctionExpression(func_expr) => func_expr.return_type.is_some(), + Expression::ArrowFunctionExpression(arrow_func_expr) => { + arrow_func_expr.return_type.is_some() + } + _ => false, + } + } +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass = vec![ + ("jest.mock('random-number');", None), + ( + " + jest.mock('../moduleName', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock('./module', () => ({ + ...jest.requireActual('./module'), + foo: jest.fn() + })); + ", + None, + ), + ( + " + jest.mock('bar', () => ({ + ...jest.requireActual('bar'), + foo: jest.fn() + })); + ", + None, + ), + ( + " + jest.doMock('./module', (): typeof import('./module') => ({ + ...jest.requireActual('./module'), + foo: jest.fn() + })); + ", + None, + ), + ( + " + jest.mock('../moduleName', function (): typeof import('../moduleName') { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock('../moduleName', function (): (() => number) { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock<() => number>('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest['doMock']<() => number>('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock( + '../moduleName', + () => { + return jest.fn(() => 42) + }, + {virtual: true}, + ); + ", + None, + ), + // Should not match + ( + " + mockito<() => number>('foo', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ]; + + let fail = vec![ + ( + " + jest.mock('../moduleName', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock(\"./module\", () => ({ + ...jest.requireActual('./module'), + foo: jest.fn() + })); + ", + None, + ), + ( + " + jest.mock('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.doMock('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest['mock']('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + const moduleToMock = 'random-num'; + jest.mock(moduleToMock, () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ]; + + let fix = vec![ + ( + " + jest.mock('../moduleName', () => { + return jest.fn(() => 42); + }); + ", + " + jest.mock('../moduleName', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.mock('./module', () => ({ + ...jest.requireActual('./module'), + foo: jest.fn() + })); + ", + " + jest.mock('./module', () => ({ + ...jest.requireActual('./module'), + foo: jest.fn() + })); + ", + None, + ), + ( + " + jest.mock('random-num', () => { + return jest.fn(() => 42); + }); + ", + " + jest.mock('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest.doMock('random-num', () => { + return jest.fn(() => 42); + }); + ", + " + jest.doMock('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ( + " + jest['mock']('random-num', () => { + return jest.fn(() => 42); + }); + ", + " + jest['mock']('random-num', () => { + return jest.fn(() => 42); + }); + ", + None, + ), + ]; + + Tester::new(NoUntypedMockFactory::NAME, pass, fail) + .with_jest_plugin(true) + .expect_fix(fix) + .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/no_untyped_mock_factory.snap b/crates/oxc_linter/src/snapshots/no_untyped_mock_factory.snap new file mode 100644 index 0000000000000..6fe0dd474d4fe --- /dev/null +++ b/crates/oxc_linter/src/snapshots/no_untyped_mock_factory.snap @@ -0,0 +1,58 @@ +--- +source: crates/oxc_linter/src/tester.rs +assertion_line: 151 +expression: no_untyped_mock_factory +--- + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:2:22] + 1 │ + 2 │ jest.mock('../moduleName', () => { + · ──── + 3 │ return jest.fn(() => 42); + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("../moduleName")` + + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:2:22] + 1 │ + 2 │ jest.mock("./module", () => ({ + · ──── + 3 │ ...jest.requireActual('./module'), + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("./module")` + + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:2:22] + 1 │ + 2 │ jest.mock('random-num', () => { + · ──── + 3 │ return jest.fn(() => 42); + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("random-num")` + + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:2:22] + 1 │ + 2 │ jest.doMock('random-num', () => { + · ────── + 3 │ return jest.fn(() => 42); + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("random-num")` + + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:2:22] + 1 │ + 2 │ jest['mock']('random-num', () => { + · ────── + 3 │ return jest.fn(() => 42); + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("random-num")` + + ⚠ eslint-plugin-jest(no-untyped-mock-factory): Disallow using `jest.mock()` factories without an explicit type parameter. + ╭─[no_untyped_mock_factory.tsx:3:22] + 2 │ const moduleToMock = 'random-num'; + 3 │ jest.mock(moduleToMock, () => { + · ──── + 4 │ return jest.fn(() => 42); + ╰──── + help: Add a type parameter to the mock factory such as `typeof import("moduleToMock")` From 75edb49c432f9c372726fcf213a7fe4b6cb3d2ff Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 26 Mar 2024 20:56:13 +0800 Subject: [PATCH 2/8] chore: add CHANGELOG.md --- CHANGELOG.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000000000..938306289bbfe --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,7 @@ +# Changelog + +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). + +## [Unreleased] From fe12617315f66e7abd4cd7b4ffe74ba1506c16f5 Mon Sep 17 00:00:00 2001 From: Ali Rezvani <3788964+rzvxa@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:51:31 +0330 Subject: [PATCH 3/8] refactor(transformer): pass options via context. (#2794) With this PR all transformers would get their `AstBuilder` and options via `TransformerCtx`. --- crates/oxc_transformer/src/context.rs | 15 +- .../src/es2015/arrow_functions.rs | 16 +- .../src/es2015/duplicate_keys.rs | 7 +- .../src/es2015/function_name.rs | 31 +- .../oxc_transformer/src/es2015/instanceof.rs | 37 +- crates/oxc_transformer/src/es2015/literals.rs | 13 +- .../oxc_transformer/src/es2015/new_target.rs | 49 +- .../src/es2015/shorthand_properties.rs | 8 +- .../src/es2015/template_literals.rs | 8 +- .../src/es2016/exponentiation_operator.rs | 78 ++-- .../src/es2019/json_strings.rs | 7 +- .../src/es2019/optional_catch_binding.rs | 8 +- .../src/es2020/nullish_coalescing_operator.rs | 72 ++- .../es2021/logical_assignment_operators.rs | 120 +++-- .../src/es2021/numeric_separator.rs | 9 +- .../src/es2022/class_static_block.rs | 8 +- .../src/es3/property_literals.rs | 9 +- crates/oxc_transformer/src/lib.rs | 50 +- .../src/proposals/decorators.rs | 435 +++++++++--------- crates/oxc_transformer/src/react_jsx/mod.rs | 157 ++++--- .../src/regexp/regexp_flags.rs | 8 +- crates/oxc_transformer/src/typescript/mod.rs | 288 ++++++------ 22 files changed, 716 insertions(+), 717 deletions(-) diff --git a/crates/oxc_transformer/src/context.rs b/crates/oxc_transformer/src/context.rs index 9d6f8ac3e0a3b..074d0d2c23bd1 100644 --- a/crates/oxc_transformer/src/context.rs +++ b/crates/oxc_transformer/src/context.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, cell::{Ref, RefCell, RefMut}, mem, rc::Rc, @@ -9,16 +10,24 @@ use oxc_diagnostics::Error; use oxc_semantic::{ScopeId, ScopeTree, Semantic, SymbolId, SymbolTable}; use oxc_span::{CompactStr, SourceType}; +use crate::TransformOptions; + #[derive(Clone)] pub struct TransformerCtx<'a> { pub ast: Rc>, + pub options: Cow<'a, TransformOptions>, semantic: Rc>>, errors: Rc>>, } impl<'a> TransformerCtx<'a> { - pub fn new(ast: Rc>, semantic: Rc>>) -> Self { - Self { ast, semantic, errors: Rc::new(RefCell::new(vec![])) } + pub fn new(ast: Rc>, semantic: Semantic<'a>, options: TransformOptions) -> Self { + Self { + ast, + semantic: Rc::new(RefCell::new(semantic)), + options: Cow::Owned(options), + errors: Rc::new(RefCell::new(vec![])), + } } pub fn semantic(&self) -> Ref<'_, Semantic<'a>> { @@ -51,7 +60,7 @@ impl<'a> TransformerCtx<'a> { } /// Push a Transform Error - pub fn error>(&mut self, error: T) { + pub fn error>(&self, error: T) { self.errors.borrow_mut().push(error.into()); } } diff --git a/crates/oxc_transformer/src/es2015/arrow_functions.rs b/crates/oxc_transformer/src/es2015/arrow_functions.rs index 69e20dbcf6fe8..173e1c43ee0df 100644 --- a/crates/oxc_transformer/src/es2015/arrow_functions.rs +++ b/crates/oxc_transformer/src/es2015/arrow_functions.rs @@ -7,7 +7,6 @@ use oxc_span::{Atom, SPAN}; use serde::Deserialize; use crate::context::TransformerCtx; -use crate::options::TransformOptions; use crate::TransformTarget; /// ES2015 Arrow Functions @@ -61,15 +60,12 @@ impl<'a> VisitMut<'a> for ArrowFunctions<'a> { } impl<'a> ArrowFunctions<'a> { - pub fn new( - ast: Rc>, - _: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2015 || options.arrow_functions.is_some()).then(|| { - let nodes = ast.new_vec(); - Self { ast, uid: 0, nodes, has_this: false, insert: false } - }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.arrow_functions.is_some()) + .then(|| { + let nodes = ctx.ast.new_vec(); + Self { ast: ctx.ast, uid: 0, nodes, has_this: false, insert: false } + }) } fn get_this_name(&self) -> Atom<'a> { diff --git a/crates/oxc_transformer/src/es2015/duplicate_keys.rs b/crates/oxc_transformer/src/es2015/duplicate_keys.rs index 5ac043703f0c2..9a34f76baa121 100644 --- a/crates/oxc_transformer/src/es2015/duplicate_keys.rs +++ b/crates/oxc_transformer/src/es2015/duplicate_keys.rs @@ -5,7 +5,7 @@ use std::{collections::HashSet, rc::Rc}; use oxc_ast::{ast::*, AstBuilder}; use oxc_span::{CompactStr, SPAN}; -use crate::options::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2015: Duplicate Keys /// @@ -17,8 +17,9 @@ pub struct DuplicateKeys<'a> { } impl<'a> DuplicateKeys<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2015 || options.duplicate_keys).then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.duplicate_keys) + .then_some(Self { ast: ctx.ast }) } pub fn transform_object_expression<'b>(&mut self, obj_expr: &'b mut ObjectExpression<'a>) { diff --git a/crates/oxc_transformer/src/es2015/function_name.rs b/crates/oxc_transformer/src/es2015/function_name.rs index 239fa4dd08994..3288b84d4602b 100644 --- a/crates/oxc_transformer/src/es2015/function_name.rs +++ b/crates/oxc_transformer/src/es2015/function_name.rs @@ -1,7 +1,5 @@ -use std::rc::Rc; - // use lazy_static::lazy_static; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_semantic::ScopeId; use oxc_span::{Atom, Span}; use oxc_syntax::identifier::is_identifier_part; @@ -9,7 +7,6 @@ use oxc_syntax::operator::AssignmentOperator; // use regex::Regex; use crate::context::TransformerCtx; -use crate::options::TransformOptions; use crate::utils::is_valid_identifier; use crate::TransformTarget; @@ -19,23 +16,19 @@ use crate::TransformTarget; /// * /// * pub struct FunctionName<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, unicode_escapes: bool, } impl<'a> FunctionName<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2015 || options.function_name).then_some(Self { - ast, - ctx, - // TODO hook up the plugin - unicode_escapes: true, - }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.function_name).then_some( + Self { + ctx, + // TODO hook up the plugin + unicode_escapes: true, + }, + ) } pub fn transform_assignment_expression(&mut self, expr: &mut AssignmentExpression<'a>) { @@ -125,7 +118,7 @@ impl<'a> FunctionName<'a> { // If we're shadowing, change the name if count > 0 { - id.name = self.ast.new_atom(&format!("{}{}", id.name, count)); + id.name = self.ctx.ast.new_atom(&format!("{}{}", id.name, count)); } if func.id.is_none() { @@ -157,13 +150,13 @@ impl<'a> FunctionName<'a> { atom.chars().map(|c| if is_identifier_part(c) { c } else { '_' }).collect::(); let id = if id.is_empty() { - self.ast.new_atom("_") + self.ctx.ast.new_atom("_") } else if id == "eval" || id == "arguments" || id == "null" || !is_valid_identifier(&id, true) { - self.ast.new_atom(&format!("_{id}")) + self.ctx.ast.new_atom(&format!("_{id}")) } else { atom.clone() }; diff --git a/crates/oxc_transformer/src/es2015/instanceof.rs b/crates/oxc_transformer/src/es2015/instanceof.rs index f4b0552046012..64cc08985d284 100644 --- a/crates/oxc_transformer/src/es2015/instanceof.rs +++ b/crates/oxc_transformer/src/es2015/instanceof.rs @@ -1,12 +1,10 @@ -use oxc_ast::{ast::*, AstBuilder, AstKind}; +use oxc_ast::{ast::*, AstKind}; use oxc_semantic::AstNodeId; use oxc_span::SPAN; -use std::rc::Rc; use oxc_syntax::operator::BinaryOperator; use crate::context::TransformerCtx; -use crate::options::TransformOptions; use crate::TransformTarget; /// ES2015: instanceof @@ -15,18 +13,13 @@ use crate::TransformTarget; /// * /// * pub struct Instanceof<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, } impl<'a> Instanceof<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2015 || options.instanceof) - .then_some(Self { ast, ctx }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.instanceof) + .then_some(Self { ctx }) } pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { @@ -54,23 +47,23 @@ impl<'a> Instanceof<'a> { return; } - let object = self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, - "babelHelpers".into(), - )); + let object = self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, "babelHelpers".into()), + ); let property = IdentifierName::new(SPAN, "instanceof".into()); - let helper = self.ast.member_expression(MemberExpression::StaticMemberExpression( - StaticMemberExpression { span: SPAN, object, property, optional: false }, - )); + let helper = + self.ctx.ast.member_expression(MemberExpression::StaticMemberExpression( + StaticMemberExpression { span: SPAN, object, property, optional: false }, + )); - let left = self.ast.copy(left); - let right = self.ast.copy(right); - let mut args = self.ast.new_vec_with_capacity(2); + let left = self.ctx.ast.copy(left); + let right = self.ctx.ast.copy(right); + let mut args = self.ctx.ast.new_vec_with_capacity(2); args.push(Argument::Expression(left)); args.push(Argument::Expression(right)); - *expr = self.ast.call_expression(SPAN, helper, args, false, None); + *expr = self.ctx.ast.call_expression(SPAN, helper, args, false, None); } } } diff --git a/crates/oxc_transformer/src/es2015/literals.rs b/crates/oxc_transformer/src/es2015/literals.rs index 75c439bdb8292..06bc9f768183a 100644 --- a/crates/oxc_transformer/src/es2015/literals.rs +++ b/crates/oxc_transformer/src/es2015/literals.rs @@ -2,12 +2,9 @@ use std::rc::Rc; use oxc_ast::{ast::*, AstBuilder}; -use crate::{ - context::TransformerCtx, - options::{TransformOptions, TransformTarget}, -}; +use crate::{context::TransformerCtx, options::TransformTarget}; -/// ES2015: Shorthand Properties +/// ES2015: Literals /// /// References: /// * @@ -19,8 +16,8 @@ pub struct Literals<'a> { impl<'a> Literals<'a> { #![allow(clippy::unused_self)] - pub fn new(ctx: TransformerCtx<'a>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2015 || options.literals) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.literals) .then_some(Self { _ast: ctx.ast }) } @@ -33,7 +30,7 @@ impl<'a> Literals<'a> { if let [b'0', b'b' | b'B' | b'o' | b'O'] = lit.raw[0..2].as_bytes() { // Set binary and octal raw values to empty, It would force the codegen, - // go generate them from their value. + // to generate them from their value. lit.raw = ""; } } diff --git a/crates/oxc_transformer/src/es2015/new_target.rs b/crates/oxc_transformer/src/es2015/new_target.rs index a9341826fb397..4d8d21125304e 100644 --- a/crates/oxc_transformer/src/es2015/new_target.rs +++ b/crates/oxc_transformer/src/es2015/new_target.rs @@ -1,10 +1,9 @@ -use crate::{context::TransformerCtx, TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, TransformTarget}; use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_diagnostics::miette; use oxc_span::{Atom, Span, SPAN}; use oxc_syntax::operator::BinaryOperator; -use std::rc::Rc; /// ES2015: New Target /// @@ -12,7 +11,6 @@ use std::rc::Rc; /// * /// * pub struct NewTarget<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, kinds: Vec<'a, NewTargetKind<'a>>, } @@ -75,17 +73,10 @@ impl<'a> NewTarget<'a> { } impl<'a> NewTarget<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - let kinds = ast.new_vec(); - (options.target < TransformTarget::ES2015 || options.new_target).then_some(Self { - ast, - ctx, - kinds, - }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + let kinds = ctx.ast.new_vec(); + (ctx.options.target < TransformTarget::ES2015 || ctx.options.new_target) + .then_some(Self { ctx, kinds }) } fn push(&mut self, kind: NewTargetKind<'a>) { @@ -97,9 +88,9 @@ impl<'a> NewTarget<'a> { } fn create_constructor_expr(&self, span: Span) -> Expression<'a> { - self.ast.static_member_expression( + self.ctx.ast.static_member_expression( span, - self.ast.this_expression(span), + self.ctx.ast.this_expression(span), IdentifierName { span, name: "constructor".into() }, false, ) @@ -114,33 +105,35 @@ impl<'a> NewTarget<'a> { *expr = self.create_constructor_expr(meta.span); } NewTargetKind::Method => { - *expr = self.ast.void_0(); + *expr = self.ctx.ast.void_0(); } NewTargetKind::Function(name) => { // TODO packages/babel-helper-create-class-features-plugin/src/fields.ts#L192 unshadow // It will mutate previous ast node, it is difficult at now. let id = name.clone().unwrap_or_else(|| { - self.ast.new_atom(self.ctx.scopes().generate_uid("target").as_str()) + self.ctx + .ast + .new_atom(self.ctx.scopes().generate_uid("target").as_str()) }); - let test = self.ast.binary_expression( + let test = self.ctx.ast.binary_expression( SPAN, - self.ast.this_expression(SPAN), + self.ctx.ast.this_expression(SPAN), BinaryOperator::Instanceof, - self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, id, - )), + self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, id), + ), ); - let consequent = self.ast.static_member_expression( + let consequent = self.ctx.ast.static_member_expression( SPAN, - self.ast.this_expression(SPAN), + self.ctx.ast.this_expression(SPAN), IdentifierName { span: SPAN, name: "constructor".into() }, false, ); - *expr = self.ast.conditional_expression( + *expr = self.ctx.ast.conditional_expression( meta.span, test, consequent, - self.ast.void_0(), + self.ctx.ast.void_0(), ); } } diff --git a/crates/oxc_transformer/src/es2015/shorthand_properties.rs b/crates/oxc_transformer/src/es2015/shorthand_properties.rs index 2d198841ecfbf..0151042e0da7d 100644 --- a/crates/oxc_transformer/src/es2015/shorthand_properties.rs +++ b/crates/oxc_transformer/src/es2015/shorthand_properties.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use oxc_ast::{ast::*, AstBuilder}; use oxc_span::GetSpan; -use crate::options::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2015: Shorthand Properties /// @@ -15,9 +15,9 @@ pub struct ShorthandProperties<'a> { } impl<'a> ShorthandProperties<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2015 || options.shorthand_properties) - .then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.shorthand_properties) + .then_some(Self { ast: ctx.ast }) } pub fn transform_object_property<'b>(&mut self, obj_prop: &'b mut ObjectProperty<'a>) { diff --git a/crates/oxc_transformer/src/es2015/template_literals.rs b/crates/oxc_transformer/src/es2015/template_literals.rs index 31fbbfe122155..336410d3946bb 100644 --- a/crates/oxc_transformer/src/es2015/template_literals.rs +++ b/crates/oxc_transformer/src/es2015/template_literals.rs @@ -3,7 +3,7 @@ use oxc_ast::{ast::*, AstBuilder}; use oxc_span::{Atom, Span, SPAN}; use std::{mem, rc::Rc}; -use crate::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, TransformTarget}; /// ES2015: Template Literals /// @@ -15,9 +15,9 @@ pub struct TemplateLiterals<'a> { } impl<'a> TemplateLiterals<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2015 || options.template_literals) - .then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2015 || ctx.options.template_literals) + .then_some(Self { ast: ctx.ast }) } pub fn transform_expression<'b>(&mut self, expr: &'b mut Expression<'a>) { diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index d8d9c0999ddc9..e233b31293c35 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -1,15 +1,9 @@ -use std::rc::Rc; - use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_span::{Atom, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator}; -use crate::{ - context::TransformerCtx, - options::{TransformOptions, TransformTarget}, - utils::CreateVars, -}; +use crate::{context::TransformerCtx, options::TransformTarget, utils::CreateVars}; /// ES2016: Exponentiation Operator /// @@ -18,7 +12,6 @@ use crate::{ /// * /// * pub struct ExponentiationOperator<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, vars: Vec<'a, VariableDeclarator<'a>>, } @@ -39,23 +32,21 @@ impl<'a> CreateVars<'a> for ExponentiationOperator<'a> { } impl<'a> ExponentiationOperator<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2016 || options.exponentiation_operator).then(|| { - let vars = ast.new_vec(); - Self { ast, ctx, vars } - }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2016 || ctx.options.exponentiation_operator).then( + || { + let vars = ctx.ast.new_vec(); + Self { ctx, vars } + }, + ) } pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { // left ** right if let Expression::BinaryExpression(binary_expr) = expr { if binary_expr.operator == BinaryOperator::Exponential { - let left = self.ast.move_expression(&mut binary_expr.left); - let right = self.ast.move_expression(&mut binary_expr.right); + let left = self.ctx.ast.move_expression(&mut binary_expr.left); + let right = self.ctx.ast.move_expression(&mut binary_expr.right); *expr = self.math_pow(left, right); } } @@ -63,21 +54,21 @@ impl<'a> ExponentiationOperator<'a> { // left **= right if let Expression::AssignmentExpression(assign_expr) = expr { if assign_expr.operator == AssignmentOperator::Exponential { - let mut nodes = self.ast.new_vec(); - let left = self.ast.move_assignment_target(&mut assign_expr.left); + let mut nodes = self.ctx.ast.new_vec(); + let left = self.ctx.ast.move_assignment_target(&mut assign_expr.left); let Some(Exploded { reference, uid }) = self.explode(left, &mut nodes) else { return; }; - let right = self.ast.move_expression(&mut assign_expr.right); + let right = self.ctx.ast.move_expression(&mut assign_expr.right); let right = self.math_pow(uid, right); - let assign_expr = self.ast.assignment_expression( + let assign_expr = self.ctx.ast.assignment_expression( Span::default(), AssignmentOperator::Assign, reference, right, ); nodes.push(assign_expr); - *expr = self.ast.sequence_expression(Span::default(), nodes); + *expr = self.ctx.ast.sequence_expression(Span::default(), nodes); } } } @@ -85,13 +76,14 @@ impl<'a> ExponentiationOperator<'a> { /// `left ** right` -> `Math.pow(left, right)` fn math_pow(&mut self, left: Expression<'a>, right: Expression<'a>) -> Expression<'a> { let ident_math = IdentifierReference::new(Span::default(), Atom::from("Math")); - let object = self.ast.identifier_reference_expression(ident_math); + let object = self.ctx.ast.identifier_reference_expression(ident_math); let property = IdentifierName::new(Span::default(), Atom::from("pow")); - let callee = self.ast.static_member_expression(Span::default(), object, property, false); - let mut arguments = self.ast.new_vec_with_capacity(2); + let callee = + self.ctx.ast.static_member_expression(Span::default(), object, property, false); + let mut arguments = self.ctx.ast.new_vec_with_capacity(2); arguments.push(Argument::Expression(left)); arguments.push(Argument::Expression(right)); - self.ast.call_expression(Span::default(), callee, arguments, false, None) + self.ctx.ast.call_expression(Span::default(), callee, arguments, false, None) } /// Change `lhs **= 2` to `var temp; temp = lhs, lhs = Math.pow(temp, 2);`. @@ -110,7 +102,7 @@ impl<'a> ExponentiationOperator<'a> { return None; } }; - let obj = self.get_obj_ref(self.ast.copy(&node), nodes)?; + let obj = self.get_obj_ref(self.ctx.ast.copy(&node), nodes)?; let (reference, uid) = match node { SimpleAssignmentTarget::AssignmentTargetIdentifier(ident) => { let reference = AssignmentTarget::SimpleAssignmentTarget( @@ -122,25 +114,25 @@ impl<'a> ExponentiationOperator<'a> { let computed = member_expr.is_computed(); let prop = self.get_prop_ref(member_expr.unbox(), nodes)?; let optional = false; - let obj_clone = self.ast.copy(&obj); + let obj_clone = self.ctx.ast.copy(&obj); let span = Span::default(); let (reference, uid) = match &prop { Expression::Identifier(ident) if !computed => { let ident = IdentifierName::new(span, ident.name.clone()); ( - self.ast.static_member(span, obj_clone, ident.clone(), optional), - self.ast.static_member_expression(span, obj, ident, optional), + self.ctx.ast.static_member(span, obj_clone, ident.clone(), optional), + self.ctx.ast.static_member_expression(span, obj, ident, optional), ) } _ => { - let prop_clone = self.ast.copy(&prop); + let prop_clone = self.ctx.ast.copy(&prop); ( - self.ast.computed_member(span, obj_clone, prop_clone, optional), - self.ast.computed_member_expression(span, obj, prop, optional), + self.ctx.ast.computed_member(span, obj_clone, prop_clone, optional), + self.ctx.ast.computed_member_expression(span, obj, prop, optional), ) } }; - (self.ast.simple_assignment_target_member_expression(reference), uid) + (self.ctx.ast.simple_assignment_target_member_expression(reference), uid) } _ => return None, }; @@ -163,10 +155,10 @@ impl<'a> ExponentiationOperator<'a> { // this variable is declared in scope so we can be 100% sure // that evaluating it multiple times won't trigger a getter // or something else - return Some(self.ast.identifier_reference_expression(ident.unbox())); + return Some(self.ctx.ast.identifier_reference_expression(ident.unbox())); } // could possibly trigger a getter so we need to only evaluate it once - self.ast.identifier_reference_expression(ident.unbox()) + self.ctx.ast.identifier_reference_expression(ident.unbox()) } SimpleAssignmentTarget::MemberAssignmentTarget(member_expr) => { let expr = match member_expr.unbox() { @@ -208,7 +200,7 @@ impl<'a> ExponentiationOperator<'a> { MemberExpression::StaticMemberExpression(expr) => { let ident = expr.property; let string_literal = StringLiteral::new(Span::default(), ident.name); - return Some(self.ast.literal_string_expression(string_literal)); + return Some(self.ctx.ast.literal_string_expression(string_literal)); } MemberExpression::PrivateFieldExpression(_) => { // From babel: "We can't generate property ref for private name, please install `@babel/plugin-transform-class-properties`" @@ -225,10 +217,10 @@ impl<'a> ExponentiationOperator<'a> { ) -> Expression<'a> { let ident = self.create_new_var(&expr); // Add new reference `_name = name` to nodes - let target = self.ast.simple_assignment_target_identifier(ident.clone()); + let target = self.ctx.ast.simple_assignment_target_identifier(ident.clone()); let op = AssignmentOperator::Assign; - nodes.push(self.ast.assignment_expression(Span::default(), op, target, expr)); - self.ast.identifier_reference_expression(ident) + nodes.push(self.ctx.ast.assignment_expression(Span::default(), op, target, expr)); + self.ctx.ast.identifier_reference_expression(ident) } } diff --git a/crates/oxc_transformer/src/es2019/json_strings.rs b/crates/oxc_transformer/src/es2019/json_strings.rs index 02083ae7482f4..dc9c4c7d4df37 100644 --- a/crates/oxc_transformer/src/es2019/json_strings.rs +++ b/crates/oxc_transformer/src/es2019/json_strings.rs @@ -4,7 +4,7 @@ use oxc_ast::{ast::*, AstBuilder}; use oxc_span::Atom; use oxc_syntax::identifier::{LS, PS}; -use crate::options::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2019: Json Strings /// @@ -16,8 +16,9 @@ pub struct JsonStrings<'a> { } impl<'a> JsonStrings<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2019 || options.json_strings).then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2019 || ctx.options.json_strings) + .then_some(Self { ast: ctx.ast }) } // Allow `U+2028` and `U+2029` in string literals diff --git a/crates/oxc_transformer/src/es2019/optional_catch_binding.rs b/crates/oxc_transformer/src/es2019/optional_catch_binding.rs index 004784f66e619..43ef63a73ac34 100644 --- a/crates/oxc_transformer/src/es2019/optional_catch_binding.rs +++ b/crates/oxc_transformer/src/es2019/optional_catch_binding.rs @@ -3,7 +3,7 @@ use std::rc::Rc; use oxc_ast::{ast::*, AstBuilder}; use oxc_span::SPAN; -use crate::options::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2019: Optional Catch Binding /// @@ -15,9 +15,9 @@ pub struct OptionalCatchBinding<'a> { } impl<'a> OptionalCatchBinding<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2019 || options.optional_catch_binding) - .then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2019 || ctx.options.optional_catch_binding) + .then_some(Self { ast: ctx.ast }) } pub fn transform_catch_clause<'b>(&mut self, clause: &'b mut CatchClause<'a>) { diff --git a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs index 951d1b053b5ee..571c2a714ad14 100644 --- a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs +++ b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs @@ -1,16 +1,11 @@ use serde::Deserialize; -use std::rc::Rc; use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_span::SPAN; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator}; -use crate::{ - context::TransformerCtx, - options::{TransformOptions, TransformTarget}, - utils::CreateVars, -}; +use crate::{context::TransformerCtx, options::TransformTarget, utils::CreateVars}; #[derive(Debug, Default, Clone, Copy, Deserialize)] pub struct NullishCoalescingOperatorOptions { @@ -27,10 +22,7 @@ pub struct NullishCoalescingOperatorOptions { /// * pub struct NullishCoalescingOperator<'a> { no_document_all: bool, - - ast: Rc>, ctx: TransformerCtx<'a>, - vars: Vec<'a, VariableDeclarator<'a>>, } @@ -45,18 +37,15 @@ impl<'a> CreateVars<'a> for NullishCoalescingOperator<'a> { } impl<'a> NullishCoalescingOperator<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2020 || options.nullish_coalescing_operator.is_some()) - .then(|| { - let no_document_all = options.assumptions.no_document_all - || options.nullish_coalescing_operator.is_some_and(|o| o.loose); - let vars = ast.new_vec(); - Self { no_document_all, ast, ctx, vars } - }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2020 + || ctx.options.nullish_coalescing_operator.is_some()) + .then(|| { + let no_document_all = ctx.options.assumptions.no_document_all + || ctx.options.nullish_coalescing_operator.is_some_and(|o| o.loose); + let vars = ctx.ast.new_vec(); + Self { no_document_all, ctx, vars } + }) } pub fn transform_expression(&mut self, expr: &mut Expression<'a>) { @@ -71,33 +60,38 @@ impl<'a> NullishCoalescingOperator<'a> { // skip creating extra reference when `left` is static if self.ctx.symbols().is_static(&logical_expr.left) { - reference = self.ast.copy(&logical_expr.left); - assignment = self.ast.copy(&logical_expr.left); + reference = self.ctx.ast.copy(&logical_expr.left); + assignment = self.ctx.ast.copy(&logical_expr.left); } else { let ident = self.create_new_var(&logical_expr.left); - reference = self.ast.identifier_reference_expression(ident.clone()); - let left = self.ast.simple_assignment_target_identifier(ident); - let right = self.ast.copy(&logical_expr.left); + reference = self.ctx.ast.identifier_reference_expression(ident.clone()); + let left = self.ctx.ast.simple_assignment_target_identifier(ident); + let right = self.ctx.ast.copy(&logical_expr.left); assignment = - self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right); + self.ctx.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right); }; let test = if self.no_document_all { - let null = self.ast.literal_null_expression(NullLiteral::new(SPAN)); - self.ast.binary_expression(SPAN, assignment, BinaryOperator::Inequality, null) + let null = self.ctx.ast.literal_null_expression(NullLiteral::new(SPAN)); + self.ctx.ast.binary_expression(SPAN, assignment, BinaryOperator::Inequality, null) } else { let op = BinaryOperator::StrictInequality; - let null = self.ast.literal_null_expression(NullLiteral::new(SPAN)); - let left = self.ast.binary_expression(SPAN, self.ast.copy(&assignment), op, null); - - let right = - self.ast.binary_expression(SPAN, self.ast.copy(&reference), op, self.ast.void_0()); - - self.ast.logical_expression(SPAN, left, LogicalOperator::And, right) + let null = self.ctx.ast.literal_null_expression(NullLiteral::new(SPAN)); + let left = + self.ctx.ast.binary_expression(SPAN, self.ctx.ast.copy(&assignment), op, null); + + let right = self.ctx.ast.binary_expression( + SPAN, + self.ctx.ast.copy(&reference), + op, + self.ctx.ast.void_0(), + ); + + self.ctx.ast.logical_expression(SPAN, left, LogicalOperator::And, right) }; - let right = self.ast.move_expression(&mut logical_expr.right); + let right = self.ctx.ast.move_expression(&mut logical_expr.right); - *expr = self.ast.conditional_expression(SPAN, test, reference, right); + *expr = self.ctx.ast.conditional_expression(SPAN, test, reference, right); } } diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index f6e7b6915a126..a33f311fba1cc 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -1,15 +1,9 @@ -use std::rc::Rc; - use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_span::SPAN; use oxc_syntax::operator::{AssignmentOperator, LogicalOperator}; -use crate::{ - context::TransformerCtx, - options::{TransformOptions, TransformTarget}, - utils::CreateVars, -}; +use crate::{context::TransformerCtx, options::TransformTarget, utils::CreateVars}; /// ES2021: Logical Assignment Operators /// @@ -17,9 +11,7 @@ use crate::{ /// * /// * pub struct LogicalAssignmentOperators<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, - vars: Vec<'a, VariableDeclarator<'a>>, } @@ -34,17 +26,12 @@ impl<'a> CreateVars<'a> for LogicalAssignmentOperators<'a> { } impl<'a> LogicalAssignmentOperators<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - (options.target < TransformTarget::ES2021 || options.logical_assignment_operators).then( - || { - let vars = ast.new_vec(); - Self { ast, ctx, vars } - }, - ) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2021 || ctx.options.logical_assignment_operators) + .then(|| { + let vars = ctx.ast.new_vec(); + Self { ctx, vars } + }) } pub fn transform_expression<'b>(&mut self, expr: &'b mut Expression<'a>) { @@ -69,8 +56,9 @@ impl<'a> LogicalAssignmentOperators<'a> { match &assignment_expr.left { AssignmentTarget::SimpleAssignmentTarget(target) => match target { SimpleAssignmentTarget::AssignmentTargetIdentifier(ident) => { - left_expr = self.ast.identifier_reference_expression((*ident).clone()); - assign_target = self.ast.simple_assignment_target_identifier((*ident).clone()); + left_expr = self.ctx.ast.identifier_reference_expression((*ident).clone()); + assign_target = + self.ctx.ast.simple_assignment_target_identifier((*ident).clone()); } SimpleAssignmentTarget::MemberAssignmentTarget(member_expr) => { let op = AssignmentOperator::Assign; @@ -79,31 +67,31 @@ impl<'a> LogicalAssignmentOperators<'a> { match &**member_expr { MemberExpression::StaticMemberExpression(static_expr) => { if let Some(ident) = self.maybe_generate_memoised(&static_expr.object) { - let right = self.ast.copy(&static_expr.object); - let mut expr = self.ast.copy(static_expr); + let right = self.ctx.ast.copy(&static_expr.object); + let mut expr = self.ctx.ast.copy(static_expr); let target = - self.ast.simple_assignment_target_identifier(ident.clone()); + self.ctx.ast.simple_assignment_target_identifier(ident.clone()); expr.object = - self.ast.assignment_expression(SPAN, op, target, right); - left_expr = self.ast.member_expression( + self.ctx.ast.assignment_expression(SPAN, op, target, right); + left_expr = self.ctx.ast.member_expression( MemberExpression::StaticMemberExpression(expr), ); - let mut expr = self.ast.copy(static_expr); - expr.object = self.ast.identifier_reference_expression(ident); + let mut expr = self.ctx.ast.copy(static_expr); + expr.object = self.ctx.ast.identifier_reference_expression(ident); assign_target = - self.ast.simple_assignment_target_member_expression( + self.ctx.ast.simple_assignment_target_member_expression( MemberExpression::StaticMemberExpression(expr), ); } else { - left_expr = self.ast.member_expression( + left_expr = self.ctx.ast.member_expression( MemberExpression::StaticMemberExpression( - self.ast.copy(static_expr), + self.ctx.ast.copy(static_expr), ), ); assign_target = - self.ast.simple_assignment_target_member_expression( - self.ast.copy(member_expr), + self.ctx.ast.simple_assignment_target_member_expression( + self.ctx.ast.copy(member_expr), ); }; } @@ -115,66 +103,70 @@ impl<'a> LogicalAssignmentOperators<'a> { let property_ident = self.maybe_generate_memoised(&computed_expr.expression); - let right = self.ast.copy(&computed_expr.object); - let mut expr = self.ast.copy(computed_expr); + let right = self.ctx.ast.copy(&computed_expr.object); + let mut expr = self.ctx.ast.copy(computed_expr); let target = - self.ast.simple_assignment_target_identifier(ident.clone()); + self.ctx.ast.simple_assignment_target_identifier(ident.clone()); expr.object = - self.ast.assignment_expression(SPAN, op, target, right); + self.ctx.ast.assignment_expression(SPAN, op, target, right); if let Some(property_ident) = &property_ident { - let left = self.ast.simple_assignment_target_identifier( + let left = self.ctx.ast.simple_assignment_target_identifier( property_ident.clone(), ); - let right = self.ast.copy(&computed_expr.expression); + let right = self.ctx.ast.copy(&computed_expr.expression); expr.expression = - self.ast.assignment_expression(SPAN, op, left, right); + self.ctx.ast.assignment_expression(SPAN, op, left, right); } - left_expr = self.ast.member_expression( + left_expr = self.ctx.ast.member_expression( MemberExpression::ComputedMemberExpression(expr), ); // `(_a[_b$y] = c)` part - let mut expr = self.ast.copy(computed_expr); - expr.object = self.ast.identifier_reference_expression(ident); + let mut expr = self.ctx.ast.copy(computed_expr); + expr.object = self.ctx.ast.identifier_reference_expression(ident); if let Some(property_ident) = property_ident { - expr.expression = - self.ast.identifier_reference_expression(property_ident); + expr.expression = self + .ctx + .ast + .identifier_reference_expression(property_ident); } assign_target = - self.ast.simple_assignment_target_member_expression( + self.ctx.ast.simple_assignment_target_member_expression( MemberExpression::ComputedMemberExpression(expr), ); } else { let property_ident = self.maybe_generate_memoised(&computed_expr.expression); - // let right = self.ast.copy(&computed_expr.object); - let mut expr = self.ast.copy(computed_expr); + // let right = self.ctx.ast.copy(&computed_expr.object); + let mut expr = self.ctx.ast.copy(computed_expr); // let target = AssignmentTarget::SimpleAssignmentTarget( - // self.ast.simple_assignment_target_identifier(ident.clone()), + // self.ctx.ast.simple_assignment_target_identifier(ident.clone()), // ); // expr.object = - // self.ast.assignment_expression(span, op, target, right); + // self.ctx.ast.assignment_expression(span, op, target, right); if let Some(property_ident) = &property_ident { - let left = self.ast.simple_assignment_target_identifier( + let left = self.ctx.ast.simple_assignment_target_identifier( property_ident.clone(), ); - let right = self.ast.copy(&computed_expr.expression); + let right = self.ctx.ast.copy(&computed_expr.expression); expr.expression = - self.ast.assignment_expression(SPAN, op, left, right); + self.ctx.ast.assignment_expression(SPAN, op, left, right); } - left_expr = self.ast.member_expression( + left_expr = self.ctx.ast.member_expression( MemberExpression::ComputedMemberExpression(expr), ); - let mut expr = self.ast.copy(computed_expr); - // expr.object = self.ast.identifier_reference_expression(ident); + let mut expr = self.ctx.ast.copy(computed_expr); + // expr.object = self.ctx.ast.identifier_reference_expression(ident); if let Some(property_ident) = property_ident { - expr.expression = - self.ast.identifier_reference_expression(property_ident); + expr.expression = self + .ctx + .ast + .identifier_reference_expression(property_ident); } assign_target = - self.ast.simple_assignment_target_member_expression( + self.ctx.ast.simple_assignment_target_member_expression( MemberExpression::ComputedMemberExpression(expr), ); }; @@ -191,10 +183,10 @@ impl<'a> LogicalAssignmentOperators<'a> { }; let assign_op = AssignmentOperator::Assign; - let right = self.ast.move_expression(&mut assignment_expr.right); - let right = self.ast.assignment_expression(SPAN, assign_op, assign_target, right); + let right = self.ctx.ast.move_expression(&mut assignment_expr.right); + let right = self.ctx.ast.assignment_expression(SPAN, assign_op, assign_target, right); - let logical_expr = self.ast.logical_expression(SPAN, left_expr, operator, right); + let logical_expr = self.ctx.ast.logical_expression(SPAN, left_expr, operator, right); *expr = logical_expr; } diff --git a/crates/oxc_transformer/src/es2021/numeric_separator.rs b/crates/oxc_transformer/src/es2021/numeric_separator.rs index 3c31e2d7b5e98..a507fb107248e 100644 --- a/crates/oxc_transformer/src/es2021/numeric_separator.rs +++ b/crates/oxc_transformer/src/es2021/numeric_separator.rs @@ -1,10 +1,7 @@ use oxc_ast::ast::*; use oxc_span::Atom; -use crate::{ - context::TransformerCtx, - options::{TransformOptions, TransformTarget}, -}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2021: Numeric Separator /// @@ -17,8 +14,8 @@ pub struct NumericSeparator<'a> { impl<'a> NumericSeparator<'a> { #![allow(clippy::unused_self)] - pub fn new(ctx: TransformerCtx<'a>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2021 || options.numeric_separator) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2021 || ctx.options.numeric_separator) .then_some(Self { ctx }) } diff --git a/crates/oxc_transformer/src/es2022/class_static_block.rs b/crates/oxc_transformer/src/es2022/class_static_block.rs index bacdb983a11c4..bea4adba51caa 100644 --- a/crates/oxc_transformer/src/es2022/class_static_block.rs +++ b/crates/oxc_transformer/src/es2022/class_static_block.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashSet, rc::Rc}; use oxc_ast::{ast::*, AstBuilder}; use oxc_span::{Atom, SPAN}; -use crate::options::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, options::TransformTarget}; /// ES2022: Class Static Block /// @@ -15,9 +15,9 @@ pub struct ClassStaticBlock<'a> { } impl<'a> ClassStaticBlock<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2022 || options.class_static_block) - .then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target < TransformTarget::ES2022 || ctx.options.class_static_block) + .then_some(Self { ast: ctx.ast }) } pub fn transform_class_body<'b>(&mut self, class_body: &'b mut ClassBody<'a>) { diff --git a/crates/oxc_transformer/src/es3/property_literals.rs b/crates/oxc_transformer/src/es3/property_literals.rs index e5c0fb05b3027..a55c742c03d79 100644 --- a/crates/oxc_transformer/src/es3/property_literals.rs +++ b/crates/oxc_transformer/src/es3/property_literals.rs @@ -2,8 +2,9 @@ use oxc_ast::{ast::*, AstBuilder}; use oxc_span::SPAN; use std::rc::Rc; +use crate::context::TransformerCtx; use crate::utils::is_valid_es3_identifier; -use crate::{TransformOptions, TransformTarget}; +use crate::TransformTarget; /// ES3: PropertyLiteral /// @@ -14,9 +15,9 @@ pub struct PropertyLiteral<'a> { } impl<'a> PropertyLiteral<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - (options.target <= TransformTarget::ES3 || options.property_literals) - .then_some(Self { ast }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + (ctx.options.target <= TransformTarget::ES3 || ctx.options.property_literals) + .then_some(Self { ast: ctx.ast }) } pub fn transform_object_property<'b>(&mut self, expr: &'b mut ObjectProperty<'a>) { diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 9e6032e348f2f..37123a934de02 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -24,7 +24,7 @@ mod tester; mod typescript; mod utils; -use std::{cell::RefCell, rc::Rc, sync::Arc}; +use std::{rc::Rc, sync::Arc}; use es2015::TemplateLiterals; use oxc_allocator::Allocator; @@ -108,39 +108,41 @@ impl<'a> Transformer<'a> { ) -> Self { let ast = Rc::new(AstBuilder::new(allocator)); let ctx = TransformerCtx::new( - Rc::clone(&ast), - Rc::new(RefCell::new(semantic)), + ast, + semantic, + options, ); Self { - ctx: ctx.clone(), - decorators: Decorators::new(Rc::clone(&ast), ctx.clone(), &options), - typescript: source_type.is_typescript().then(|| TypeScript::new(Rc::clone(&ast), ctx.clone(), &options)), - regexp_flags: RegexpFlags::new(Rc::clone(&ast), &options), + decorators: Decorators::new(ctx.clone()), + typescript: source_type.is_typescript().then(|| TypeScript::new(ctx.clone())), + regexp_flags: RegexpFlags::new(ctx.clone()), // es2022 - es2022_class_static_block: es2022::ClassStaticBlock::new(Rc::clone(&ast), &options), + es2022_class_static_block: es2022::ClassStaticBlock::new(ctx.clone()), // es2021 - es2021_logical_assignment_operators: LogicalAssignmentOperators::new(Rc::clone(&ast), ctx.clone(), &options), - es2021_numeric_separator: NumericSeparator::new(ctx.clone(), &options), + es2021_logical_assignment_operators: LogicalAssignmentOperators::new(ctx.clone()), + es2021_numeric_separator: NumericSeparator::new(ctx.clone()), // es2020 - es2020_nullish_coalescing_operators: NullishCoalescingOperator::new(Rc::clone(&ast), ctx.clone(), &options), + es2020_nullish_coalescing_operators: NullishCoalescingOperator::new(ctx.clone()), // es2019 - es2019_json_strings: JsonStrings::new(Rc::clone(&ast), &options), - es2019_optional_catch_binding: OptionalCatchBinding::new(Rc::clone(&ast), &options), + es2019_json_strings: JsonStrings::new(ctx.clone()), + es2019_optional_catch_binding: OptionalCatchBinding::new(ctx.clone()), // es2016 - es2016_exponentiation_operator: ExponentiationOperator::new(Rc::clone(&ast), ctx.clone(), &options), + es2016_exponentiation_operator: ExponentiationOperator::new(ctx.clone()), // es2015 - es2015_function_name: FunctionName::new(Rc::clone(&ast), ctx.clone(), &options), - es2015_arrow_functions: ArrowFunctions::new(Rc::clone(&ast), ctx.clone(), &options), - es2015_shorthand_properties: ShorthandProperties::new(Rc::clone(&ast), &options), - es2015_template_literals: TemplateLiterals::new(Rc::clone(&ast), &options), - es2015_duplicate_keys: DuplicateKeys::new(Rc::clone(&ast), &options), - es2015_instanceof: Instanceof::new(Rc::clone(&ast), ctx.clone(), &options), - es2015_literals: Literals::new(ctx.clone(), &options), - es2015_new_target: NewTarget::new(Rc::clone(&ast),ctx.clone(), &options), + es2015_function_name: FunctionName::new(ctx.clone()), + es2015_arrow_functions: ArrowFunctions::new(ctx.clone()), + es2015_shorthand_properties: ShorthandProperties::new(ctx.clone()), + es2015_template_literals: TemplateLiterals::new(ctx.clone()), + es2015_duplicate_keys: DuplicateKeys::new(ctx.clone()), + es2015_instanceof: Instanceof::new(ctx.clone()), + es2015_literals: Literals::new(ctx.clone()), + es2015_new_target: NewTarget::new(ctx.clone()), // other - es3_property_literal: PropertyLiteral::new(Rc::clone(&ast), &options), - react_jsx: ReactJsx::new(Rc::clone(&ast), ctx.clone(), options) + es3_property_literal: PropertyLiteral::new(ctx.clone()), + react_jsx: ReactJsx::new(ctx.clone()), + // original context + ctx, } } diff --git a/crates/oxc_transformer/src/proposals/decorators.rs b/crates/oxc_transformer/src/proposals/decorators.rs index 4cf2fb5dea0cd..cad9125964561 100644 --- a/crates/oxc_transformer/src/proposals/decorators.rs +++ b/crates/oxc_transformer/src/proposals/decorators.rs @@ -1,13 +1,13 @@ -use std::{borrow::Cow, collections::HashMap, rc::Rc}; +use std::{borrow::Cow, collections::HashMap}; use bitflags::bitflags; use oxc_allocator::{Box, Vec}; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_span::{Atom, CompactStr, SPAN}; use oxc_syntax::operator::{AssignmentOperator, LogicalOperator}; use serde::Deserialize; -use crate::{context::TransformerCtx, options::TransformOptions}; +use crate::context::TransformerCtx; /// Proposal: Decorators /// @@ -16,7 +16,6 @@ use crate::{context::TransformerCtx, options::TransformOptions}; /// * /// * pub struct Decorators<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, options: DecoratorsOptions, // Insert to the top of the program @@ -104,15 +103,10 @@ impl Version { } impl<'a> Decorators<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Option { - let top_statements = ast.new_vec(); - let bottom_statements = ast.new_vec(); - options.decorators.map(|options| Self { - ast, + pub fn new(ctx: TransformerCtx<'a>) -> Option { + let top_statements = ctx.ast.new_vec(); + let bottom_statements = ctx.ast.new_vec(); + ctx.options.decorators.map(|options| Self { ctx, options, top_statements, @@ -122,12 +116,12 @@ impl<'a> Decorators<'a> { } pub fn get_variable_declarator(&self, name: &str) -> VariableDeclarator<'a> { - let name = self.ast.new_atom(name); - self.ast.variable_declarator( + let name = self.ctx.ast.new_atom(name); + self.ctx.ast.variable_declarator( SPAN, VariableDeclarationKind::Var, BindingPattern::new_with_kind( - self.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, name)), + self.ctx.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, name)), ), None, false, @@ -139,9 +133,9 @@ impl<'a> Decorators<'a> { &self, name: &str, ) -> Option> { - let name = self.ast.new_atom(name); + let name = self.ctx.ast.new_atom(name); Some(AssignmentTargetMaybeDefault::AssignmentTarget( - self.ast.simple_assignment_target_identifier(IdentifierReference::new(SPAN, name)), + self.ctx.ast.simple_assignment_target_identifier(IdentifierReference::new(SPAN, name)), )) } @@ -158,7 +152,7 @@ impl<'a> Decorators<'a> { pub fn get_call_with_this(&self, name: &str) -> Expression<'a> { self.get_call_with_arguments( name, - self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))), + self.ctx.ast.new_vec_single(Argument::Expression(self.ctx.ast.this_expression(SPAN))), ) } @@ -167,10 +161,10 @@ impl<'a> Decorators<'a> { name: &str, arguments: Vec<'a, Argument<'a>>, ) -> Expression<'a> { - let name = self.ast.new_atom(name); - self.ast.call_expression( + let name = self.ctx.ast.new_atom(name); + self.ctx.ast.call_expression( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)), + self.ctx.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)), arguments, false, None, @@ -206,17 +200,17 @@ impl<'a> Decorators<'a> { }; if has_decorator { - self.bottom_statements.push(self.ast.module_declaration( + self.bottom_statements.push(self.ctx.ast.module_declaration( ModuleDeclaration::ExportNamedDeclaration( - self.ast.export_named_declaration( + self.ctx.ast.export_named_declaration( SPAN, None, - self.ast.new_vec_single(ExportSpecifier::new( + self.ctx.ast.new_vec_single(ExportSpecifier::new( SPAN, ModuleExportName::Identifier( IdentifierName::new( SPAN, - self.ast.new_atom( + self.ctx.ast.new_atom( class_name.as_ref().unwrap(), ), ), @@ -266,20 +260,20 @@ impl<'a> Decorators<'a> { }; if class_has_decorator { - self.bottom_statements.push(self.ast.module_declaration( + self.bottom_statements.push(self.ctx.ast.module_declaration( ModuleDeclaration::ExportNamedDeclaration( - self.ast.export_named_declaration( + self.ctx.ast.export_named_declaration( SPAN, None, - self.ast.new_vec_single(ExportSpecifier::new( + self.ctx.ast.new_vec_single(ExportSpecifier::new( SPAN, ModuleExportName::Identifier(IdentifierName::new( SPAN, - self.ast.new_atom(class_name.as_ref().unwrap()), + self.ctx.ast.new_atom(class_name.as_ref().unwrap()), )), ModuleExportName::Identifier(IdentifierName::new( SPAN, - self.ast.new_atom("default"), + self.ctx.ast.new_atom("default"), )), )), None, @@ -335,19 +329,19 @@ impl<'a> Decorators<'a> { let has_decorator = !class.decorators.is_empty(); let has_member_decorator = class.body.body.iter().any(ClassElement::has_decorator); - let mut declarations = self.ast.new_vec(); + let mut declarations = self.ctx.ast.new_vec(); - let mut c_elements = self.ast.new_vec(); - let mut e_elements = self.ast.new_vec(); + let mut c_elements = self.ctx.ast.new_vec(); + let mut e_elements = self.ctx.ast.new_vec(); let mut private_in_expression = None; let mut init_static_name = None; // insert member decorators - let mut member_decorators_vec = self.ast.new_vec(); + let mut member_decorators_vec = self.ctx.ast.new_vec(); let mut class_decorators_argument = - Argument::Expression(self.ast.array_expression(SPAN, self.ast.new_vec(), None)); + Argument::Expression(self.ctx.ast.array_expression(SPAN, self.ctx.ast.new_vec(), None)); if has_decorator { let class_name = class_name.unwrap_or_else(|| { @@ -372,13 +366,13 @@ impl<'a> Decorators<'a> { }); if decorators_exists { - let mut elements = self.ast.new_vec(); + let mut elements = self.ctx.ast.new_vec(); elements.extend(class.decorators.drain(..).map(|decorator| { - ArrayExpressionElement::Expression(self.ast.copy(&decorator.expression)) + ArrayExpressionElement::Expression(self.ctx.ast.copy(&decorator.expression)) })); class_decorators_argument = - Argument::Expression(self.ast.array_expression(SPAN, elements, None)); + Argument::Expression(self.ctx.ast.array_expression(SPAN, elements, None)); } else { let class_decs_name = self.get_unique_name("classDecs"); @@ -386,24 +380,24 @@ impl<'a> Decorators<'a> { declarations.push(self.get_variable_declarator(&class_decs_name)); // insert _classDecs = decorators; - let left = self.ast.simple_assignment_target_identifier( - IdentifierReference::new(SPAN, self.ast.new_atom(&class_decs_name)), + let left = self.ctx.ast.simple_assignment_target_identifier( + IdentifierReference::new(SPAN, self.ctx.ast.new_atom(&class_decs_name)), ); - let right = self.ast.array_expression( + let right = self.ctx.ast.array_expression( SPAN, { - let mut elements = self.ast.new_vec(); + let mut elements = self.ctx.ast.new_vec(); elements.extend(class.decorators.drain(..).map(|d| { - ArrayExpressionElement::Expression(self.ast.copy(&d.expression)) + ArrayExpressionElement::Expression(self.ctx.ast.copy(&d.expression)) })); elements }, None, ); - let assign_class_decs = self.ast.expression_statement( + let assign_class_decs = self.ctx.ast.expression_statement( SPAN, - self.ast.assignment_expression( + self.ctx.ast.assignment_expression( SPAN, AssignmentOperator::Assign, left, @@ -413,8 +407,8 @@ impl<'a> Decorators<'a> { self.top_statements.push(assign_class_decs); class_decorators_argument = - Argument::Expression(self.ast.identifier_reference_expression( - IdentifierReference::new(SPAN, self.ast.new_atom(&class_decs_name)), + Argument::Expression(self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, self.ctx.ast.new_atom(&class_decs_name)), )); } }; @@ -422,8 +416,8 @@ impl<'a> Decorators<'a> { { // insert let _className let declarations = - self.ast.new_vec_single(self.get_variable_declarator(&class_name)); - let variable_declaration = self.ast.variable_declaration( + self.ctx.ast.new_vec_single(self.get_variable_declarator(&class_name)); + let variable_declaration = self.ctx.ast.variable_declaration( SPAN, VariableDeclarationKind::Let, declarations, @@ -439,15 +433,14 @@ impl<'a> Decorators<'a> { { // call _initClass - let callee = self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, - self.ast.new_atom(&init_class_name), - )); + let callee = self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, self.ctx.ast.new_atom(&init_class_name)), + ); let call_expr = - self.ast.call_expression(SPAN, callee, self.ast.new_vec(), false, None); + self.ctx.ast.call_expression(SPAN, callee, self.ctx.ast.new_vec(), false, None); let statements = - self.ast.new_vec_single(self.ast.expression_statement(SPAN, call_expr)); - let static_block = self.ast.static_block(SPAN, statements); + self.ctx.ast.new_vec_single(self.ctx.ast.expression_statement(SPAN, call_expr)); + let static_block = self.ctx.ast.static_block(SPAN, statements); class.body.body.insert(0, static_block); } } @@ -477,7 +470,7 @@ impl<'a> Decorators<'a> { member_decorators_vec.push(ArrayExpressionElement::Expression( self.get_decorator_info( &def.key, - Some(self.ast.copy(&def.value)), + Some(self.ctx.ast.copy(&def.value)), flag, decorator, ), @@ -503,35 +496,35 @@ impl<'a> Decorators<'a> { Cow::Owned(format!("call_{}", def.key.name().unwrap())) }); - let mut arguments = self.ast.new_vec_with_capacity(2); - arguments.push(Argument::Expression(self.ast.this_expression(SPAN))); + let mut arguments = self.ctx.ast.new_vec_with_capacity(2); + arguments + .push(Argument::Expression(self.ctx.ast.this_expression(SPAN))); arguments.push(Argument::Expression( - self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, - self.ast.new_atom("v"), - )), + self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, self.ctx.ast.new_atom("v")), + ), )); let is_setter = def.kind == MethodDefinitionKind::Set; - def.value = self.ast.function( + def.value = self.ctx.ast.function( def.value.r#type, def.value.span, - self.ast.copy(&def.value.id), + self.ctx.ast.copy(&def.value.id), def.value.generator, def.value.r#async, - self.ast.copy(&def.value.this_param), - self.ast.formal_parameters( + self.ctx.ast.copy(&def.value.this_param), + self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::FormalParameter, if is_setter { - self.ast.new_vec_single(self.ast.formal_parameter( + self.ctx.ast.new_vec_single(self.ctx.ast.formal_parameter( SPAN, - self.ast.binding_pattern( - self.ast.binding_pattern_identifier( + self.ctx.ast.binding_pattern( + self.ctx.ast.binding_pattern_identifier( BindingIdentifier::new( SPAN, - self.ast.new_atom("v"), + self.ctx.ast.new_atom("v"), ), ), None, @@ -540,31 +533,31 @@ impl<'a> Decorators<'a> { None, false, false, - self.ast.new_vec(), + self.ctx.ast.new_vec(), )) } else { - self.ast.new_vec() + self.ctx.ast.new_vec() }, None, ), - Some(self.ast.function_body( + Some(self.ctx.ast.function_body( SPAN, - self.ast.new_vec(), - self.ast.new_vec_single(if is_setter { - self.ast.expression_statement( + self.ctx.ast.new_vec(), + self.ctx.ast.new_vec_single(if is_setter { + self.ctx.ast.expression_statement( SPAN, self.get_call_with_arguments(&name, arguments), ) } else { - self.ast.return_statement( + self.ctx.ast.return_statement( SPAN, Some(self.get_call_with_this(&name)), ) }), )), - self.ast.copy(&def.value.type_parameters), - self.ast.copy(&def.value.return_type), - self.ast.copy(&def.value.modifiers), + self.ctx.ast.copy(&def.value.type_parameters), + self.ctx.ast.copy(&def.value.return_type), + self.ctx.ast.copy(&def.value.modifiers), ); } else { continue; @@ -595,19 +588,20 @@ impl<'a> Decorators<'a> { } def.decorators.clear(); - let mut arguments = self - .ast - .new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))); + let mut arguments = self.ctx.ast.new_vec_single(Argument::Expression( + self.ctx.ast.this_expression(SPAN), + )); if let Some(value) = &mut def.value { - arguments.push(Argument::Expression(self.ast.move_expression(value))); + arguments + .push(Argument::Expression(self.ctx.ast.move_expression(value))); } - def.value = Some(self.ast.call_expression( + def.value = Some(self.ctx.ast.call_expression( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - self.ast.new_atom(&name), + self.ctx.ast.new_atom(&name), )), arguments, false, @@ -633,7 +627,7 @@ impl<'a> Decorators<'a> { ) { if let ClassElement::MethodDefinition(def) = constructor_element { if let Some(body) = &mut def.value.body { - body.statements.insert(0, self.ast.expression_statement(SPAN, self.get_call_with_this(&name))); + body.statements.insert(0, self.ctx.ast.expression_statement(SPAN, self.get_call_with_this(&name))); } } else { unreachable!(); @@ -642,26 +636,26 @@ impl<'a> Decorators<'a> { // if the class has no constructor, insert a empty constructor and call initProto class.body.body.insert( 0, - self.ast.class_constructor( + self.ctx.ast.class_constructor( SPAN, - self.ast.function( + self.ctx.ast.function( FunctionType::FunctionExpression, SPAN, None, false, false, None, - self.ast.formal_parameters( + self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::FormalParameter, - self.ast.new_vec(), + self.ctx.ast.new_vec(), None, ), - Some(self.ast.function_body( + Some(self.ctx.ast.function_body( SPAN, - self.ast.new_vec(), - self.ast.new_vec_single( - self.ast.expression_statement(SPAN, self.get_call_with_this(&name)) + self.ctx.ast.new_vec(), + self.ctx.ast.new_vec_single( + self.ctx.ast.expression_statement(SPAN, self.get_call_with_this(&name)) ), )), None, @@ -683,7 +677,7 @@ impl<'a> Decorators<'a> { { // insert all variable_declarator in same variable_declaration - let variable_declaration = self.ast.variable_declaration( + let variable_declaration = self.ctx.ast.variable_declaration( SPAN, VariableDeclarationKind::Var, declarations, @@ -706,19 +700,21 @@ impl<'a> Decorators<'a> { // parentClass: any, // ) {} // call babelHelpers.applyDecs2305 - let callee = self.ast.static_member_expression( + let callee = self.ctx.ast.static_member_expression( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - self.ast.new_atom("babelHelpers"), + self.ctx.ast.new_atom("babelHelpers"), )), - IdentifierName::new(SPAN, self.ast.new_atom("applyDecs2305")), + IdentifierName::new(SPAN, self.ctx.ast.new_atom("applyDecs2305")), false, ); - let mut arguments = - self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))); - arguments.push(Argument::Expression(self.ast.array_expression( + let mut arguments = self + .ctx + .ast + .new_vec_single(Argument::Expression(self.ctx.ast.this_expression(SPAN))); + arguments.push(Argument::Expression(self.ctx.ast.array_expression( SPAN, member_decorators_vec, None, @@ -726,58 +722,58 @@ impl<'a> Decorators<'a> { arguments.push(class_decorators_argument); if let Some(private_in_expression) = private_in_expression { // classDecsHaveThis - arguments.push(Argument::Expression(self.ast.literal_number_expression( + arguments.push(Argument::Expression(self.ctx.ast.literal_number_expression( // TODO: use correct number instead of `0` - self.ast.number_literal(SPAN, 0f64, "0", oxc_syntax::NumberBase::Decimal), + self.ctx.ast.number_literal(SPAN, 0f64, "0", oxc_syntax::NumberBase::Decimal), ))); // instanceBrand arguments.push(Argument::Expression(private_in_expression)); } - let mut call_expr = self.ast.call_expression(SPAN, callee, arguments, false, None); + let mut call_expr = self.ctx.ast.call_expression(SPAN, callee, arguments, false, None); if has_decorator && has_decorator == has_member_decorator { - let mut properties = self.ast.new_vec_with_capacity(2); - properties.push(self.ast.assignment_target_property_property( + let mut properties = self.ctx.ast.new_vec_with_capacity(2); + properties.push(self.ctx.ast.assignment_target_property_property( SPAN, - self.ast.property_key_identifier(IdentifierName::new(SPAN, "e".into())), - self.ast.array_assignment_target_maybe_default( + self.ctx.ast.property_key_identifier(IdentifierName::new(SPAN, "e".into())), + self.ctx.ast.array_assignment_target_maybe_default( ArrayAssignmentTarget::new_with_elements(SPAN, e_elements), ), )); - properties.push(self.ast.assignment_target_property_property( + properties.push(self.ctx.ast.assignment_target_property_property( SPAN, - self.ast.property_key_identifier(IdentifierName::new(SPAN, "c".into())), - self.ast.array_assignment_target_maybe_default( + self.ctx.ast.property_key_identifier(IdentifierName::new(SPAN, "c".into())), + self.ctx.ast.array_assignment_target_maybe_default( ArrayAssignmentTarget::new_with_elements(SPAN, c_elements), ), )); - call_expr = self.ast.assignment_expression( + call_expr = self.ctx.ast.assignment_expression( SPAN, AssignmentOperator::Assign, - self.ast.object_assignment_target(ObjectAssignmentTarget::new_with_properties( - SPAN, properties, - )), + self.ctx.ast.object_assignment_target( + ObjectAssignmentTarget::new_with_properties(SPAN, properties), + ), call_expr, ); } else if has_decorator || has_member_decorator { - call_expr = self.ast.static_member_expression( + call_expr = self.ctx.ast.static_member_expression( SPAN, call_expr, IdentifierName::new( SPAN, - self.ast.new_atom(if has_decorator { "c" } else { "e" }), + self.ctx.ast.new_atom(if has_decorator { "c" } else { "e" }), ), false, ); let left = - self.ast.array_assignment_target(ArrayAssignmentTarget::new_with_elements( + self.ctx.ast.array_assignment_target(ArrayAssignmentTarget::new_with_elements( SPAN, if has_decorator { c_elements } else { e_elements }, )); - call_expr = self.ast.assignment_expression( + call_expr = self.ctx.ast.assignment_expression( SPAN, AssignmentOperator::Assign, left, @@ -785,28 +781,29 @@ impl<'a> Decorators<'a> { ); } - let mut statements = self.ast.new_vec(); - statements.push(self.ast.expression_statement(SPAN, call_expr)); + let mut statements = self.ctx.ast.new_vec(); + statements.push(self.ctx.ast.expression_statement(SPAN, call_expr)); if let Some(init_static_name) = init_static_name { // call initStatic - let callee = self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, - self.ast.new_atom(&init_static_name), - )); - let arguments = - self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))); - statements.push(self.ast.expression_statement( + let callee = self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, self.ctx.ast.new_atom(&init_static_name)), + ); + let arguments = self + .ctx + .ast + .new_vec_single(Argument::Expression(self.ctx.ast.this_expression(SPAN))); + statements.push(self.ctx.ast.expression_statement( SPAN, - self.ast.call_expression(SPAN, callee, arguments, false, None), + self.ctx.ast.call_expression(SPAN, callee, arguments, false, None), )); } - let static_block = self.ast.static_block(SPAN, statements); + let static_block = self.ctx.ast.static_block(SPAN, statements); class.body.body.insert(0, static_block); } - Declaration::ClassDeclaration(self.ast.copy(class)) + Declaration::ClassDeclaration(self.ctx.ast.copy(class)) } /// transform version: legacy @@ -817,40 +814,42 @@ impl<'a> Decorators<'a> { ) -> Declaration<'a> { let class_binding_identifier = &class.id.clone().unwrap_or_else(|| { let class_name = class_name.unwrap_or_else(|| self.get_unique_name("class")); - BindingIdentifier::new(SPAN, self.ast.new_atom(&class_name)) + BindingIdentifier::new(SPAN, self.ctx.ast.new_atom(&class_name)) }); let class_name = BindingPattern::new_with_kind( - self.ast.binding_pattern_identifier(self.ast.copy(class_binding_identifier)), + self.ctx.ast.binding_pattern_identifier(self.ctx.ast.copy(class_binding_identifier)), ); let init = { let class_identifier_name = self.get_unique_name("class"); let class_identifier = - IdentifierReference::new(SPAN, self.ast.new_atom(&class_identifier_name)); + IdentifierReference::new(SPAN, self.ctx.ast.new_atom(&class_identifier_name)); - let decl = self.ast.variable_declaration( + let decl = self.ctx.ast.variable_declaration( SPAN, VariableDeclarationKind::Var, - self.ast.new_vec_single(self.get_variable_declarator(&class_identifier_name)), + self.ctx.ast.new_vec_single(self.get_variable_declarator(&class_identifier_name)), Modifiers::empty(), ); self.top_statements .push(Statement::Declaration(Declaration::VariableDeclaration(decl))); - let left = self.ast.simple_assignment_target_identifier(class_identifier.clone()); - let right = self.ast.class_expression(self.ast.copy(class)); + let left = self.ctx.ast.simple_assignment_target_identifier(class_identifier.clone()); + let right = self.ctx.ast.class_expression(self.ctx.ast.copy(class)); let new_expr = - self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right); + self.ctx.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right); let new_expr = class.decorators.drain(..).fold(new_expr, |new_expr, decorator| { match &decorator.expression { - Expression::Identifier(identifier) => self.ast.call_expression( + Expression::Identifier(identifier) => self.ctx.ast.call_expression( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, identifier.name.clone(), )), - self.ast.new_vec_single(Argument::Expression(self.ast.copy(&new_expr))), + self.ctx + .ast + .new_vec_single(Argument::Expression(self.ctx.ast.copy(&new_expr))), false, None, ), @@ -858,15 +857,15 @@ impl<'a> Decorators<'a> { } }); - self.ast.logical_expression( + self.ctx.ast.logical_expression( SPAN, new_expr, LogicalOperator::Or, - self.ast.identifier_reference_expression(class_identifier), + self.ctx.ast.identifier_reference_expression(class_identifier), ) }; - let declarator = self.ast.variable_declarator( + let declarator = self.ctx.ast.variable_declarator( SPAN, VariableDeclarationKind::Let, class_name, @@ -874,10 +873,10 @@ impl<'a> Decorators<'a> { false, ); - Declaration::VariableDeclaration(self.ast.variable_declaration( + Declaration::VariableDeclaration(self.ctx.ast.variable_declaration( SPAN, VariableDeclarationKind::Let, - self.ast.new_vec_single(declarator), + self.ctx.ast.new_vec_single(declarator), Modifiers::empty(), )) } @@ -892,22 +891,24 @@ impl<'a> Decorators<'a> { ) -> Expression<'a> { let name = key.name(); // [dec, flag, name, defaultValue | (o) => o.#a, (o, v) => o.#a = v] - let mut decorator_elements = self.ast.new_vec_with_capacity(2); + let mut decorator_elements = self.ctx.ast.new_vec_with_capacity(2); decorator_elements - .push(ArrayExpressionElement::Expression(self.ast.copy(&decorator.expression))); + .push(ArrayExpressionElement::Expression(self.ctx.ast.copy(&decorator.expression))); decorator_elements.push(ArrayExpressionElement::Expression( - self.ast.literal_number_expression(NumericLiteral::new( + self.ctx.ast.literal_number_expression(NumericLiteral::new( SPAN, 0f64, - self.ast.new_str(flag.to_value().to_string().as_str()), + self.ctx.ast.new_str(flag.to_value().to_string().as_str()), oxc_syntax::NumberBase::Decimal, )), )); if let Some(name) = name { - decorator_elements - .push(ArrayExpressionElement::Expression(self.ast.literal_string_expression( - StringLiteral::new(SPAN, self.ast.new_atom(&name)), - ))); + decorator_elements.push(ArrayExpressionElement::Expression( + self.ctx.ast.literal_string_expression(StringLiteral::new( + SPAN, + self.ctx.ast.new_atom(&name), + )), + )); if key.is_private_identifier() { if let Some(value) = value { @@ -916,12 +917,12 @@ impl<'a> Decorators<'a> { )); } else { // o => o.#a - let mut items = self.ast.new_vec_single(self.ast.formal_parameter( + let mut items = self.ctx.ast.new_vec_single(self.ctx.ast.formal_parameter( SPAN, - self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new( + self.ctx.ast.binding_pattern( + self.ctx.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - self.ast.new_atom("o"), + self.ctx.ast.new_atom("o"), )), None, false, @@ -929,36 +930,40 @@ impl<'a> Decorators<'a> { None, false, false, - self.ast.new_vec(), + self.ctx.ast.new_vec(), )); - let private_field = self.ast.private_field( + let private_field = self.ctx.ast.private_field( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - self.ast.new_atom("o"), + self.ctx.ast.new_atom("o"), )), - PrivateIdentifier::new(SPAN, self.ast.new_atom(&name)), + PrivateIdentifier::new(SPAN, self.ctx.ast.new_atom(&name)), false, ); - let params = self.ast.formal_parameters( + let params = self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::ArrowFormalParameters, - self.ast.copy(&items), + self.ctx.ast.copy(&items), None, ); decorator_elements.push(ArrayExpressionElement::Expression( - self.ast.arrow_function_expression( + self.ctx.ast.arrow_function_expression( SPAN, true, false, params, - self.ast.function_body( + self.ctx.ast.function_body( SPAN, - self.ast.new_vec(), - self.ast.new_vec_single(self.ast.expression_statement( - SPAN, - self.ast.member_expression(self.ast.copy(&private_field)), - )), + self.ctx.ast.new_vec(), + self.ctx.ast.new_vec_single( + self.ctx.ast.expression_statement( + SPAN, + self.ctx + .ast + .member_expression(self.ctx.ast.copy(&private_field)), + ), + ), ), None, None, @@ -967,12 +972,12 @@ impl<'a> Decorators<'a> { { // (o, v) => o.#a = v - items.push(self.ast.formal_parameter( + items.push(self.ctx.ast.formal_parameter( SPAN, - self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new( + self.ctx.ast.binding_pattern( + self.ctx.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - self.ast.new_atom("v"), + self.ctx.ast.new_atom("v"), )), None, false, @@ -980,10 +985,10 @@ impl<'a> Decorators<'a> { None, false, false, - self.ast.new_vec(), + self.ctx.ast.new_vec(), )); - let params = self.ast.formal_parameters( + let params = self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::ArrowFormalParameters, items, @@ -991,30 +996,34 @@ impl<'a> Decorators<'a> { ); decorator_elements.push(ArrayExpressionElement::Expression( - self.ast.arrow_function_expression( + self.ctx.ast.arrow_function_expression( SPAN, true, false, params, - self.ast.function_body( + self.ctx.ast.function_body( SPAN, - self.ast.new_vec(), - self.ast.new_vec_single(self.ast.expression_statement( - SPAN, - self.ast.assignment_expression( + self.ctx.ast.new_vec(), + self.ctx.ast.new_vec_single( + self.ctx.ast.expression_statement( SPAN, - AssignmentOperator::Assign, - self.ast.simple_assignment_target_member_expression( - private_field, - ), - self.ast.identifier_reference_expression( - IdentifierReference::new( - SPAN, - self.ast.new_atom("v"), + self.ctx.ast.assignment_expression( + SPAN, + AssignmentOperator::Assign, + self.ctx + .ast + .simple_assignment_target_member_expression( + private_field, + ), + self.ctx.ast.identifier_reference_expression( + IdentifierReference::new( + SPAN, + self.ctx.ast.new_atom("v"), + ), ), ), ), - )), + ), ), None, None, @@ -1024,24 +1033,24 @@ impl<'a> Decorators<'a> { } } } - self.ast.array_expression(SPAN, decorator_elements, None) + self.ctx.ast.array_expression(SPAN, decorator_elements, None) } // _ => #a in _; fn get_is_private_function(&self, name: &Atom<'a>) -> Expression<'a> { - self.ast.arrow_function_expression( + self.ctx.ast.arrow_function_expression( SPAN, true, false, - self.ast.formal_parameters( + self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::ArrowFormalParameters, - self.ast.new_vec_single(self.ast.formal_parameter( + self.ctx.ast.new_vec_single(self.ctx.ast.formal_parameter( SPAN, - self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new( + self.ctx.ast.binding_pattern( + self.ctx.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - self.ast.new_atom("_"), + self.ctx.ast.new_atom("_"), )), None, false, @@ -1049,21 +1058,21 @@ impl<'a> Decorators<'a> { None, false, false, - self.ast.new_vec(), + self.ctx.ast.new_vec(), )), None, ), - self.ast.function_body( + self.ctx.ast.function_body( SPAN, - self.ast.new_vec(), - self.ast.new_vec_single(self.ast.expression_statement( + self.ctx.ast.new_vec(), + self.ctx.ast.new_vec_single(self.ctx.ast.expression_statement( SPAN, - self.ast.private_in_expression( + self.ctx.ast.private_in_expression( SPAN, PrivateIdentifier::new(SPAN, name.clone()), - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - self.ast.new_atom("_"), + self.ctx.ast.new_atom("_"), )), ), )), diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index 9894467fe2d47..a1bbac5b36900 100644 --- a/crates/oxc_transformer/src/react_jsx/mod.rs +++ b/crates/oxc_transformer/src/react_jsx/mod.rs @@ -1,9 +1,7 @@ mod options; -use std::rc::Rc; - use oxc_allocator::Vec; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::Error, @@ -15,7 +13,7 @@ use oxc_syntax::{ }; pub use self::options::{ReactJsxOptions, ReactJsxRuntime, ReactJsxRuntimeOption}; -use crate::{context::TransformerCtx, TransformOptions}; +use crate::context::TransformerCtx; #[derive(Debug, Error, Diagnostic)] #[error("pragma and pragmaFrag cannot be set when runtime is automatic.")] @@ -48,7 +46,6 @@ struct SpreadChildrenAreNotSupported(#[label] Span); /// * /// * pub struct ReactJsx<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, options: ReactJsxOptions, @@ -102,14 +99,10 @@ impl<'a, 'b> JSXElementOrFragment<'a, 'b> { } impl<'a> ReactJsx<'a> { - pub fn new( - ast: Rc>, - mut ctx: TransformerCtx<'a>, - options: TransformOptions, - ) -> Option { - let imports = ast.new_vec(); - let jsx_options = options.react_jsx?.with_comments(&ctx.semantic()); - if options.babel_8_breaking == Some(true) { + pub fn new(ctx: TransformerCtx<'a>) -> Option { + let imports = ctx.ast.new_vec(); + let jsx_options = ctx.options.react_jsx.clone()?.with_comments(&ctx.semantic()); + if ctx.options.babel_8_breaking == Some(true) { if jsx_options.use_built_ins.is_some() { ctx.error(miette::Error::msg("@babel/plugin-transform-react-jsx: Since \"useBuiltIns\" is removed in Babel 8, you can remove it from the config.")); return None; @@ -123,8 +116,8 @@ impl<'a> ReactJsx<'a> { let default_runtime = Self::normalize_default_runtime( jsx_options.runtime.as_ref(), - options.babel_8_breaking, - &mut ctx, + ctx.options.babel_8_breaking, + &ctx, )?; let jsx_runtime_importer = @@ -134,8 +127,6 @@ impl<'a> ReactJsx<'a> { CompactStr::from(format!("{}/jsx-runtime", jsx_options.import_source)) }; Some(Self { - ast, - ctx, options: jsx_options, imports, jsx_runtime_importer, @@ -144,15 +135,16 @@ impl<'a> ReactJsx<'a> { import_jsxs: false, import_fragment: false, import_create_element: false, - babel_8_breaking: options.babel_8_breaking, + babel_8_breaking: ctx.options.babel_8_breaking, default_runtime, + ctx, }) } fn normalize_default_runtime( runtime: Option<&ReactJsxRuntimeOption>, babel_8_breaking: Option, - ctx: &mut TransformerCtx<'a>, + ctx: &TransformerCtx<'a>, ) -> Option { match runtime { Some(ReactJsxRuntimeOption::Valid(runtime)) => Some(*runtime), @@ -200,7 +192,7 @@ impl<'a> ReactJsx<'a> { return; } - let imports = self.ast.move_statement_vec(&mut self.imports); + let imports = self.ctx.ast.move_statement_vec(&mut self.imports); let index = program .body .iter() @@ -210,7 +202,7 @@ impl<'a> ReactJsx<'a> { } fn new_string_literal(&self, name: &str) -> StringLiteral<'a> { - StringLiteral::new(SPAN, self.ast.new_atom(name)) + StringLiteral::new(SPAN, self.ctx.ast.new_atom(name)) } fn add_import<'b>( @@ -300,17 +292,17 @@ impl<'a> ReactJsx<'a> { } fn add_import_statement(&mut self, imported: &str, local: &str, source: StringLiteral<'a>) { - let mut specifiers = self.ast.new_vec_with_capacity(1); + let mut specifiers = self.ctx.ast.new_vec_with_capacity(1); specifiers.push(ImportDeclarationSpecifier::ImportSpecifier(ImportSpecifier { span: SPAN, imported: ModuleExportName::Identifier(IdentifierName::new( SPAN, - self.ast.new_atom(imported), + self.ctx.ast.new_atom(imported), )), - local: BindingIdentifier::new(SPAN, self.ast.new_atom(local)), + local: BindingIdentifier::new(SPAN, self.ctx.ast.new_atom(local)), import_kind: ImportOrExportKind::Value, })); - let import_statement = self.ast.import_declaration( + let import_statement = self.ctx.ast.import_declaration( SPAN, Some(specifiers), source, @@ -318,7 +310,7 @@ impl<'a> ReactJsx<'a> { ImportOrExportKind::Value, ); let decl = - self.ast.module_declaration(ModuleDeclaration::ImportDeclaration(import_statement)); + self.ctx.ast.module_declaration(ModuleDeclaration::ImportDeclaration(import_statement)); self.imports.push(decl); } @@ -329,21 +321,23 @@ impl<'a> ReactJsx<'a> { front: bool, ) { let callee = self + .ctx .ast .identifier_reference_expression(IdentifierReference::new(SPAN, "require".into())); let arguments = self + .ctx .ast - .new_vec_single(Argument::Expression(self.ast.literal_string_expression(source))); - let init = self.ast.call_expression(SPAN, callee, arguments, false, None); - let id = self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new( + .new_vec_single(Argument::Expression(self.ctx.ast.literal_string_expression(source))); + let init = self.ctx.ast.call_expression(SPAN, callee, arguments, false, None); + let id = self.ctx.ast.binding_pattern( + self.ctx.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - self.ast.new_atom(variable_name), + self.ctx.ast.new_atom(variable_name), )), None, false, ); - let decl = self.ast.new_vec_single(self.ast.variable_declarator( + let decl = self.ctx.ast.new_vec_single(self.ctx.ast.variable_declarator( SPAN, VariableDeclarationKind::Var, id, @@ -351,7 +345,7 @@ impl<'a> ReactJsx<'a> { false, )); - let variable_declaration = self.ast.variable_declaration( + let variable_declaration = self.ctx.ast.variable_declaration( SPAN, VariableDeclarationKind::Var, decl, @@ -372,7 +366,7 @@ impl<'a> ReactJsx<'a> { let has_key_after_props_spread = e.has_key_after_props_spread(); // TODO: compute the correct capacity for both runtimes - let mut arguments = self.ast.new_vec_with_capacity(1); + let mut arguments = self.ctx.ast.new_vec_with_capacity(1); arguments.push(Argument::Expression(match e { JSXElementOrFragment::Element(e) => { @@ -389,12 +383,12 @@ impl<'a> ReactJsx<'a> { // Add `null` to second argument in classic mode if is_classic && attributes_len == 0 { - let null_expr = self.ast.literal_null_expression(NullLiteral::new(SPAN)); + let null_expr = self.ctx.ast.literal_null_expression(NullLiteral::new(SPAN)); arguments.push(Argument::Expression(null_expr)); } // The object properties for the second argument of `React.createElement` - let mut properties = self.ast.new_vec(); + let mut properties = self.ctx.ast.new_vec(); if let Some(attributes) = attributes { // TODO: compute the correct capacity for both runtimes @@ -406,7 +400,8 @@ impl<'a> ReactJsx<'a> { // deopt if spreading an object with `__proto__` key if !matches!(&spread.argument, Expression::ObjectExpression(o) if o.has_proto()) { - arguments.push(Argument::Expression(self.ast.copy(&spread.argument))); + arguments + .push(Argument::Expression(self.ctx.ast.copy(&spread.argument))); continue; } } @@ -436,7 +431,7 @@ impl<'a> ReactJsx<'a> { // Append children to object properties in automatic mode if is_automatic { - let allocator = self.ast.allocator; + let allocator = self.ctx.ast.allocator; let mut children = Vec::from_iter_in( children.iter().filter_map(|child| self.transform_jsx_child(child)), allocator, @@ -451,14 +446,14 @@ impl<'a> ReactJsx<'a> { allocator, ); need_jsxs = true; - self.ast.array_expression(SPAN, elements, None) + self.ctx.ast.array_expression(SPAN, elements, None) }; let kind = PropertyKind::Init; let ident = IdentifierName::new(SPAN, "children".into()); - let key = self.ast.property_key_identifier(ident); + let key = self.ctx.ast.property_key_identifier(ident); let object_property = - self.ast.object_property(SPAN, kind, key, value, None, false, false, false); + self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false); properties.push(ObjectPropertyKind::ObjectProperty(object_property)); } } @@ -466,7 +461,7 @@ impl<'a> ReactJsx<'a> { self.add_import(e, has_key_after_props_spread, need_jsxs); if !properties.is_empty() || is_automatic { - let object_expression = self.ast.object_expression(SPAN, properties, None); + let object_expression = self.ctx.ast.object_expression(SPAN, properties, None); arguments.push(Argument::Expression(object_expression)); } @@ -484,12 +479,12 @@ impl<'a> ReactJsx<'a> { } let callee = self.get_create_element(has_key_after_props_spread, need_jsxs); - self.ast.call_expression(SPAN, callee, arguments, false, None) + self.ctx.ast.call_expression(SPAN, callee, arguments, false, None) } fn get_react_references(&mut self) -> Expression<'a> { let ident = IdentifierReference::new(SPAN, "React".into()); - self.ast.identifier_reference_expression(ident) + self.ctx.ast.identifier_reference_expression(ident) } fn get_static_member_expression( @@ -497,10 +492,10 @@ impl<'a> ReactJsx<'a> { object_ident_name: &str, property_name: &str, ) -> Expression<'a> { - let property = IdentifierName::new(SPAN, self.ast.new_atom(property_name)); - let ident = IdentifierReference::new(SPAN, self.ast.new_atom(object_ident_name)); - let object = self.ast.identifier_reference_expression(ident); - self.ast.static_member_expression(SPAN, object, property, false) + let property = IdentifierName::new(SPAN, self.ctx.ast.new_atom(property_name)); + let ident = IdentifierReference::new(SPAN, self.ctx.ast.new_atom(object_ident_name)); + let object = self.ctx.ast.identifier_reference_expression(ident); + self.ctx.ast.static_member_expression(SPAN, object, property, false) } /// Get the callee from `pragma` and `pragmaFrag` @@ -510,8 +505,8 @@ impl<'a> ReactJsx<'a> { let property = callee.next(); property.map_or_else( || { - let ident = IdentifierReference::new(SPAN, self.ast.new_atom(member)); - self.ast.identifier_reference_expression(ident) + let ident = IdentifierReference::new(SPAN, self.ctx.ast.new_atom(member)); + self.ctx.ast.identifier_reference_expression(ident) }, |property_name| self.get_static_member_expression(member, property_name), ) @@ -527,7 +522,7 @@ impl<'a> ReactJsx<'a> { if self.options.pragma == "React.createElement" { let object = self.get_react_references(); let property = IdentifierName::new(SPAN, "createElement".into()); - return self.ast.static_member_expression(SPAN, object, property, false); + return self.ctx.ast.static_member_expression(SPAN, object, property, false); } self.get_call_expression_callee(self.options.pragma.as_ref()) @@ -556,7 +551,7 @@ impl<'a> ReactJsx<'a> { self.get_static_member_expression(object_ident_name, name) } else { let ident = IdentifierReference::new(SPAN, name.into()); - self.ast.identifier_reference_expression(ident) + self.ctx.ast.identifier_reference_expression(ident) } } } @@ -568,7 +563,7 @@ impl<'a> ReactJsx<'a> { if self.options.pragma_frag == "React.Fragment" { let object = self.get_react_references(); let property = IdentifierName::new(SPAN, "Fragment".into()); - return self.ast.static_member_expression(SPAN, object, property, false); + return self.ctx.ast.static_member_expression(SPAN, object, property, false); } self.get_call_expression_callee(self.options.pragma_frag.as_ref()) @@ -578,7 +573,7 @@ impl<'a> ReactJsx<'a> { self.get_static_member_expression("_reactJsxRuntime", "Fragment") } else { let ident = IdentifierReference::new(SPAN, "_Fragment".into()); - self.ast.identifier_reference_expression(ident) + self.ctx.ast.identifier_reference_expression(ident) } } } @@ -589,16 +584,17 @@ impl<'a> ReactJsx<'a> { JSXAttributeName::Identifier(ident) => { let name = ident.name.clone(); if ident.name.contains('-') { - let expr = self.ast.literal_string_expression(StringLiteral::new(SPAN, name)); - self.ast.property_key_expression(expr) + let expr = + self.ctx.ast.literal_string_expression(StringLiteral::new(SPAN, name)); + self.ctx.ast.property_key_expression(expr) } else { - self.ast.property_key_identifier(IdentifierName::new(SPAN, name)) + self.ctx.ast.property_key_identifier(IdentifierName::new(SPAN, name)) } } JSXAttributeName::NamespacedName(name) => { - let name = self.ast.new_atom(&name.to_string()); - let expr = self.ast.literal_string_expression(StringLiteral::new(SPAN, name)); - self.ast.property_key_expression(expr) + let name = self.ctx.ast.new_atom(&name.to_string()); + let expr = self.ctx.ast.literal_string_expression(StringLiteral::new(SPAN, name)); + self.ctx.ast.property_key_expression(expr) } } } @@ -608,11 +604,13 @@ impl<'a> ReactJsx<'a> { JSXElementName::Identifier(ident) => { let name = ident.name.clone(); if name == "this" { - self.ast.this_expression(SPAN) + self.ctx.ast.this_expression(SPAN) } else if ident.name.chars().next().is_some_and(|c| c.is_ascii_lowercase()) { - self.ast.literal_string_expression(StringLiteral::new(SPAN, name)) + self.ctx.ast.literal_string_expression(StringLiteral::new(SPAN, name)) } else { - self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)) + self.ctx + .ast + .identifier_reference_expression(IdentifierReference::new(SPAN, name)) } } JSXElementName::MemberExpression(member_expr) => { @@ -623,8 +621,9 @@ impl<'a> ReactJsx<'a> { self.ctx.error(NamespaceDoesNotSupport(name.span)); } - let string_literal = StringLiteral::new(SPAN, self.ast.new_atom(&name.to_string())); - self.ast.literal_string_expression(string_literal) + let string_literal = + StringLiteral::new(SPAN, self.ctx.ast.new_atom(&name.to_string())); + self.ctx.ast.literal_string_expression(string_literal) } } } @@ -640,17 +639,17 @@ impl<'a> ReactJsx<'a> { let key = self.get_attribute_name(&attr.name); let value = self.transform_jsx_attribute_value(attr.value.as_ref()); let object_property = - self.ast.object_property(SPAN, kind, key, value, None, false, false, false); + self.ctx.ast.object_property(SPAN, kind, key, value, None, false, false, false); let object_property = ObjectPropertyKind::ObjectProperty(object_property); properties.push(object_property); } JSXAttributeItem::SpreadAttribute(attr) => match &attr.argument { Expression::ObjectExpression(expr) if !expr.has_proto() => { - properties.extend(self.ast.copy(&expr.properties)); + properties.extend(self.ctx.ast.copy(&expr.properties)); } expr => { - let argument = self.ast.copy(expr); - let spread_property = self.ast.spread_element(SPAN, argument); + let argument = self.ctx.ast.copy(expr); + let spread_property = self.ctx.ast.spread_element(SPAN, argument); let object_property = ObjectPropertyKind::SpreadProperty(spread_property); properties.push(object_property); } @@ -665,8 +664,8 @@ impl<'a> ReactJsx<'a> { match value { Some(JSXAttributeValue::StringLiteral(s)) => { let jsx_text = Self::decode_entities(s.value.as_str()); - let literal = StringLiteral::new(s.span, self.ast.new_atom(&jsx_text)); - self.ast.literal_string_expression(literal) + let literal = StringLiteral::new(s.span, self.ctx.ast.new_atom(&jsx_text)); + self.ctx.ast.literal_string_expression(literal) } Some(JSXAttributeValue::Element(e)) => { self.transform_jsx(&JSXElementOrFragment::Element(e)) @@ -675,19 +674,19 @@ impl<'a> ReactJsx<'a> { self.transform_jsx(&JSXElementOrFragment::Fragment(e)) } Some(JSXAttributeValue::ExpressionContainer(c)) => match &c.expression { - JSXExpression::Expression(e) => self.ast.copy(e), + JSXExpression::Expression(e) => self.ctx.ast.copy(e), JSXExpression::EmptyExpression(_e) => { - self.ast.literal_boolean_expression(BooleanLiteral::new(SPAN, true)) + self.ctx.ast.literal_boolean_expression(BooleanLiteral::new(SPAN, true)) } }, - None => self.ast.literal_boolean_expression(BooleanLiteral::new(SPAN, true)), + None => self.ctx.ast.literal_boolean_expression(BooleanLiteral::new(SPAN, true)), } } fn transform_jsx_member_expression(&self, expr: &JSXMemberExpression<'a>) -> Expression<'a> { let object = match &expr.object { JSXMemberExpressionObject::Identifier(ident) => { - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, ident.name.clone(), )) @@ -697,14 +696,14 @@ impl<'a> ReactJsx<'a> { } }; let property = IdentifierName::new(SPAN, expr.property.name.clone()); - self.ast.static_member_expression(SPAN, object, property, false) + self.ctx.ast.static_member_expression(SPAN, object, property, false) } fn transform_jsx_child(&mut self, child: &JSXChild<'a>) -> Option> { match child { JSXChild::Text(text) => self.transform_jsx_text(text.value.as_str()), JSXChild::ExpressionContainer(e) => match &e.expression { - JSXExpression::Expression(e) => Some(self.ast.copy(e)), + JSXExpression::Expression(e) => Some(self.ctx.ast.copy(e)), JSXExpression::EmptyExpression(_) => None, }, JSXChild::Element(e) => Some(self.transform_jsx(&JSXElementOrFragment::Element(e))), @@ -718,8 +717,8 @@ impl<'a> ReactJsx<'a> { fn transform_jsx_text(&self, text: &str) -> Option> { Self::fixup_whitespace_and_decode_entities(text).map(|s| { - let s = StringLiteral::new(SPAN, self.ast.new_atom(&s)); - self.ast.literal_string_expression(s) + let s = StringLiteral::new(SPAN, self.ctx.ast.new_atom(&s)); + self.ctx.ast.literal_string_expression(s) }) } diff --git a/crates/oxc_transformer/src/regexp/regexp_flags.rs b/crates/oxc_transformer/src/regexp/regexp_flags.rs index dd001c7421429..225118a1be4a3 100644 --- a/crates/oxc_transformer/src/regexp/regexp_flags.rs +++ b/crates/oxc_transformer/src/regexp/regexp_flags.rs @@ -3,7 +3,7 @@ use oxc_span::{Atom, SPAN}; use std::rc::Rc; -use crate::{TransformOptions, TransformTarget}; +use crate::{context::TransformerCtx, TransformOptions, TransformTarget}; /// Transforms unsupported regex flags into Regex constructors. /// @@ -20,9 +20,9 @@ pub struct RegexpFlags<'a> { } impl<'a> RegexpFlags<'a> { - pub fn new(ast: Rc>, options: &TransformOptions) -> Option { - let transform_flags = Self::from_transform_target(options); - (!transform_flags.is_empty()).then_some(Self { ast, transform_flags }) + pub fn new(ctx: TransformerCtx<'a>) -> Option { + let transform_flags = Self::from_transform_target(&ctx.options); + (!transform_flags.is_empty()).then_some(Self { ast: ctx.ast, transform_flags }) } fn from_transform_target(options: &TransformOptions) -> RegExpFlags { diff --git a/crates/oxc_transformer/src/typescript/mod.rs b/crates/oxc_transformer/src/typescript/mod.rs index 18962cbbdf5fb..55b23f0c77dbd 100644 --- a/crates/oxc_transformer/src/typescript/mod.rs +++ b/crates/oxc_transformer/src/typescript/mod.rs @@ -1,5 +1,5 @@ use oxc_allocator::{Box, Vec}; -use oxc_ast::{ast::*, AstBuilder}; +use oxc_ast::ast::*; use oxc_semantic::SymbolFlags; use oxc_span::{Atom, SPAN}; use oxc_syntax::{ @@ -7,12 +7,12 @@ use oxc_syntax::{ NumberBase, }; use rustc_hash::{FxHashMap, FxHashSet}; -use std::{mem, rc::Rc}; +use std::mem; mod options; pub use self::options::TypescriptOptions; -use crate::{context::TransformerCtx, utils::is_valid_identifier, TransformOptions}; +use crate::{context::TransformerCtx, utils::is_valid_identifier}; /// Transform TypeScript /// @@ -21,7 +21,6 @@ use crate::{context::TransformerCtx, utils::is_valid_identifier, TransformOption /// * /// * pub struct TypeScript<'a> { - ast: Rc>, ctx: TransformerCtx<'a>, export_name_set: FxHashSet>, options: TypescriptOptions, @@ -29,17 +28,12 @@ pub struct TypeScript<'a> { } impl<'a> TypeScript<'a> { - pub fn new( - ast: Rc>, - ctx: TransformerCtx<'a>, - options: &TransformOptions, - ) -> Self { + pub fn new(ctx: TransformerCtx<'a>) -> Self { Self { - ast, - ctx, export_name_set: FxHashSet::default(), - options: options.typescript.clone().unwrap_or_default(), + options: ctx.options.typescript.clone().unwrap_or_default(), namespace_arg_names: FxHashMap::default(), + ctx, } } @@ -226,16 +220,16 @@ impl<'a> TypeScript<'a> { // explicit esm if module_declaration_len > 0 && module_declaration_len == delete_indexes_len { - let empty_export = self.ast.export_named_declaration( + let empty_export = self.ctx.ast.export_named_declaration( SPAN, None, - self.ast.new_vec(), + self.ctx.ast.new_vec(), None, ImportOrExportKind::Value, None, ); let export_decl = ModuleDeclaration::ExportNamedDeclaration(empty_export); - program.body.push(self.ast.module_declaration(export_decl)); + program.body.push(self.ctx.ast.module_declaration(export_decl)); } } @@ -272,13 +266,13 @@ impl<'a> TypeScript<'a> { members: &mut Vec<'a, TSEnumMember<'a>>, enum_name: &Atom<'a>, ) -> Vec<'a, Statement<'a>> { - let mut default_init = self.ast.literal_number_expression(NumericLiteral { + let mut default_init = self.ctx.ast.literal_number_expression(NumericLiteral { span: SPAN, value: 0.0, raw: "0", base: NumberBase::Decimal, }); - let mut statements = self.ast.new_vec(); + let mut statements = self.ctx.ast.new_vec(); for member in members.iter_mut() { let (member_name, member_span) = match &member.id { @@ -288,42 +282,47 @@ impl<'a> TypeScript<'a> { | TSEnumMemberName::NumericLiteral(..) => unreachable!(), }; - let mut init = - self.ast.move_expression(member.initializer.as_mut().unwrap_or(&mut default_init)); + let mut init = self + .ctx + .ast + .move_expression(member.initializer.as_mut().unwrap_or(&mut default_init)); let is_str = init.is_string_literal(); let mut self_ref = { - let obj = self.ast.identifier_reference_expression(IdentifierReference::new( + let obj = self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, enum_name.clone(), )); let expr = self + .ctx .ast .literal_string_expression(StringLiteral::new(SPAN, member_name.clone())); - self.ast.computed_member_expression(SPAN, obj, expr, false) + self.ctx.ast.computed_member_expression(SPAN, obj, expr, false) }; if is_valid_identifier(member_name, true) { let ident = IdentifierReference::new(member_span, member_name.clone()); - self_ref = self.ast.identifier_reference_expression(ident.clone()); - let init = mem::replace(&mut init, self.ast.identifier_reference_expression(ident)); + self_ref = self.ctx.ast.identifier_reference_expression(ident.clone()); + let init = + mem::replace(&mut init, self.ctx.ast.identifier_reference_expression(ident)); let kind = VariableDeclarationKind::Const; let decls = { - let mut decls = self.ast.new_vec(); + let mut decls = self.ctx.ast.new_vec(); let binding_identifier = BindingIdentifier::new(SPAN, member_name.clone()); let binding_pattern_kind = - self.ast.binding_pattern_identifier(binding_identifier); - let binding = self.ast.binding_pattern(binding_pattern_kind, None, false); - let decl = self.ast.variable_declarator(SPAN, kind, binding, Some(init), false); + self.ctx.ast.binding_pattern_identifier(binding_identifier); + let binding = self.ctx.ast.binding_pattern(binding_pattern_kind, None, false); + let decl = + self.ctx.ast.variable_declarator(SPAN, kind, binding, Some(init), false); decls.push(decl); decls }; - let decl = self.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); + let decl = self.ctx.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); let stmt: Statement<'_> = Statement::Declaration(Declaration::VariableDeclaration(decl)); @@ -332,57 +331,63 @@ impl<'a> TypeScript<'a> { // Foo["x"] = init let member_expr = { - let obj = self.ast.identifier_reference_expression(IdentifierReference::new( + let obj = self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, enum_name.clone(), )); let expr = self + .ctx .ast .literal_string_expression(StringLiteral::new(SPAN, member_name.clone())); - self.ast.computed_member(SPAN, obj, expr, false) + self.ctx.ast.computed_member(SPAN, obj, expr, false) }; - let left = self.ast.simple_assignment_target_member_expression(member_expr); + let left = self.ctx.ast.simple_assignment_target_member_expression(member_expr); let mut expr = - self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, init); + self.ctx.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, init); // Foo[Foo["x"] = init] = "x" if !is_str { let member_expr = { - let obj = self.ast.identifier_reference_expression(IdentifierReference::new( - SPAN, - enum_name.clone(), - )); - self.ast.computed_member(SPAN, obj, expr, false) + let obj = self.ctx.ast.identifier_reference_expression( + IdentifierReference::new(SPAN, enum_name.clone()), + ); + self.ctx.ast.computed_member(SPAN, obj, expr, false) }; - let left = self.ast.simple_assignment_target_member_expression(member_expr); + let left = self.ctx.ast.simple_assignment_target_member_expression(member_expr); let right = self + .ctx .ast .literal_string_expression(StringLiteral::new(SPAN, member_name.clone())); - expr = - self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right); + expr = self.ctx.ast.assignment_expression( + SPAN, + AssignmentOperator::Assign, + left, + right, + ); } - statements.push(self.ast.expression_statement(member.span, expr)); + statements.push(self.ctx.ast.expression_statement(member.span, expr)); // 1 + Foo["x"] default_init = { - let one = self.ast.literal_number_expression(NumericLiteral { + let one = self.ctx.ast.literal_number_expression(NumericLiteral { span: SPAN, value: 1.0, raw: "1", base: NumberBase::Decimal, }); - self.ast.binary_expression(SPAN, one, BinaryOperator::Addition, self_ref) + self.ctx.ast.binary_expression(SPAN, one, BinaryOperator::Addition, self_ref) }; } let enum_ref = self + .ctx .ast .identifier_reference_expression(IdentifierReference::new(SPAN, enum_name.clone())); // return Foo; - let return_stmt = self.ast.return_statement(SPAN, Some(enum_ref)); + let return_stmt = self.ctx.ast.return_statement(SPAN, Some(enum_ref)); statements.push(return_stmt); statements @@ -390,10 +395,13 @@ impl<'a> TypeScript<'a> { fn transform_ts_type_name(&self, type_name: &mut TSTypeName<'a>) -> Expression<'a> { match type_name { - TSTypeName::IdentifierReference(reference) => self.ast.identifier_reference_expression( - IdentifierReference::new(SPAN, reference.name.clone()), - ), - TSTypeName::QualifiedName(qualified_name) => self.ast.static_member_expression( + TSTypeName::IdentifierReference(reference) => { + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( + SPAN, + reference.name.clone(), + )) + } + TSTypeName::QualifiedName(qualified_name) => self.ctx.ast.static_member_expression( SPAN, self.transform_ts_type_name(&mut qualified_name.left), qualified_name.right.clone(), @@ -417,22 +425,22 @@ impl<'a> TypeScript<'a> { let kind = VariableDeclarationKind::Var; let decls = { let binding_identifier = BindingIdentifier::new(SPAN, decl.id.name.clone()); - let binding_pattern_kind = self.ast.binding_pattern_identifier(binding_identifier); - let binding = self.ast.binding_pattern(binding_pattern_kind, None, false); + let binding_pattern_kind = self.ctx.ast.binding_pattern_identifier(binding_identifier); + let binding = self.ctx.ast.binding_pattern(binding_pattern_kind, None, false); let init = match &mut decl.module_reference.0 { TSModuleReference::TypeName(type_name) => self.transform_ts_type_name(type_name), TSModuleReference::ExternalModuleReference(reference) => { - let callee = self.ast.identifier_reference_expression( + let callee = self.ctx.ast.identifier_reference_expression( IdentifierReference::new(SPAN, "require".into()), ); - let arguments = self.ast.new_vec_single(Argument::Expression( - self.ast.literal_string_expression(reference.expression.clone()), + let arguments = self.ctx.ast.new_vec_single(Argument::Expression( + self.ctx.ast.literal_string_expression(reference.expression.clone()), )); - self.ast.call_expression(SPAN, callee, arguments, false, None) + self.ctx.ast.call_expression(SPAN, callee, arguments, false, None) } }; - self.ast.new_vec_single(self.ast.variable_declarator( + self.ctx.ast.new_vec_single(self.ctx.ast.variable_declarator( SPAN, kind, binding, @@ -441,7 +449,7 @@ impl<'a> TypeScript<'a> { )) }; let variable_declaration = - self.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); + self.ctx.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); Declaration::VariableDeclaration(variable_declaration) } @@ -467,15 +475,22 @@ impl<'a> TypeScript<'a> { let span = decl.span; let ident = decl.id.clone(); - let kind = self.ast.binding_pattern_identifier(ident); - let id = self.ast.binding_pattern(kind, None, false); + let kind = self.ctx.ast.binding_pattern_identifier(ident); + let id = self.ctx.ast.binding_pattern(kind, None, false); - let mut params = self.ast.new_vec(); + let mut params = self.ctx.ast.new_vec(); // ((Foo) => { - params.push(self.ast.formal_parameter(SPAN, id, None, false, false, self.ast.new_vec())); + params.push(self.ctx.ast.formal_parameter( + SPAN, + id, + None, + false, + false, + self.ctx.ast.new_vec(), + )); - let params = self.ast.formal_parameters( + let params = self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::ArrowFormalParameters, params, @@ -485,38 +500,39 @@ impl<'a> TypeScript<'a> { // Foo[Foo["X"] = 0] = "X"; let enum_name = decl.id.name.clone(); let statements = self.transform_ts_enum_members(&mut decl.members, &enum_name); - let body = self.ast.function_body(decl.span, self.ast.new_vec(), statements); + let body = self.ctx.ast.function_body(decl.span, self.ctx.ast.new_vec(), statements); let callee = - self.ast.arrow_function_expression(SPAN, false, false, params, body, None, None); + self.ctx.ast.arrow_function_expression(SPAN, false, false, params, body, None, None); // })(Foo || {}); - let mut arguments = self.ast.new_vec(); + let mut arguments = self.ctx.ast.new_vec(); let op = LogicalOperator::Or; let left = self + .ctx .ast .identifier_reference_expression(IdentifierReference::new(SPAN, enum_name.clone())); - let right = self.ast.object_expression(SPAN, self.ast.new_vec(), None); - let expression = self.ast.logical_expression(SPAN, left, op, right); + let right = self.ctx.ast.object_expression(SPAN, self.ctx.ast.new_vec(), None); + let expression = self.ctx.ast.logical_expression(SPAN, left, op, right); arguments.push(Argument::Expression(expression)); - let call_expression = self.ast.call_expression(SPAN, callee, arguments, false, None); + let call_expression = self.ctx.ast.call_expression(SPAN, callee, arguments, false, None); let kind = VariableDeclarationKind::Var; let decls = { - let mut decls = self.ast.new_vec(); + let mut decls = self.ctx.ast.new_vec(); let binding_identifier = BindingIdentifier::new(SPAN, enum_name.clone()); - let binding_pattern_kind = self.ast.binding_pattern_identifier(binding_identifier); - let binding = self.ast.binding_pattern(binding_pattern_kind, None, false); + let binding_pattern_kind = self.ctx.ast.binding_pattern_identifier(binding_identifier); + let binding = self.ctx.ast.binding_pattern(binding_pattern_kind, None, false); let decl = - self.ast.variable_declarator(SPAN, kind, binding, Some(call_expression), false); + self.ctx.ast.variable_declarator(SPAN, kind, binding, Some(call_expression), false); decls.push(decl); decls }; let variable_declaration = - self.ast.variable_declaration(span, kind, decls, Modifiers::empty()); + self.ctx.ast.variable_declaration(span, kind, decls, Modifiers::empty()); Some(Declaration::VariableDeclaration(variable_declaration)) } @@ -562,7 +578,7 @@ impl<'a> TypeScript<'a> { return None; } - Some(Statement::Declaration(self.ast.move_declaration(declaration))) + Some(Statement::Declaration(self.ctx.ast.move_declaration(declaration))) } /// Insert let declaration for ts module block @@ -593,22 +609,23 @@ impl<'a> TypeScript<'a> { let kind = VariableDeclarationKind::Let; let decls = { let binding_identifier = BindingIdentifier::new(SPAN, name.clone()); - let binding_pattern_kind = self.ast.binding_pattern_identifier(binding_identifier); - let binding = self.ast.binding_pattern(binding_pattern_kind, None, false); - let decl = self.ast.variable_declarator(SPAN, kind, binding, None, false); - self.ast.new_vec_single(decl) + let binding_pattern_kind = + self.ctx.ast.binding_pattern_identifier(binding_identifier); + let binding = self.ctx.ast.binding_pattern(binding_pattern_kind, None, false); + let decl = self.ctx.ast.variable_declarator(SPAN, kind, binding, None, false); + self.ctx.ast.new_vec_single(decl) }; let variable_declaration = - self.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); + self.ctx.ast.variable_declaration(SPAN, kind, decls, Modifiers::empty()); let decl = Declaration::VariableDeclaration(variable_declaration); let stmt = if is_export { - self.ast.module_declaration(ModuleDeclaration::ExportNamedDeclaration( - self.ast.export_named_declaration( + self.ctx.ast.module_declaration(ModuleDeclaration::ExportNamedDeclaration( + self.ctx.ast.export_named_declaration( SPAN, Some(decl), - self.ast.new_vec(), + self.ctx.ast.new_vec(), None, ImportOrExportKind::Value, None, @@ -624,7 +641,7 @@ impl<'a> TypeScript<'a> { fn get_namespace_arg_name(&mut self, name: &Atom<'a>) -> Atom<'a> { let count = self.namespace_arg_names.entry(name.clone()).or_insert(0); *count += 1; - self.ast.new_atom(&format!( + self.ctx.ast.new_atom(&format!( "_{name}{}", if *count > 1 { count.to_string() } else { String::new() } )) @@ -646,36 +663,40 @@ impl<'a> TypeScript<'a> { let body_statements = match &mut block.body { TSModuleDeclarationBody::TSModuleDeclaration(decl) => { let transformed_module_block = self.transform_ts_module_block(decl); - self.ast.new_vec_single(transformed_module_block) + self.ctx.ast.new_vec_single(transformed_module_block) } TSModuleDeclarationBody::TSModuleBlock(ts_module_block) => { - self.ast.move_statement_vec(&mut ts_module_block.body) + self.ctx.ast.move_statement_vec(&mut ts_module_block.body) } }; let name = block.id.name(); let callee = { - let body = self.ast.function_body(SPAN, self.ast.new_vec(), body_statements); + let body = self.ctx.ast.function_body(SPAN, self.ctx.ast.new_vec(), body_statements); let arg_name = self.get_namespace_arg_name(name); - let params = self.ast.formal_parameters( + let params = self.ctx.ast.formal_parameters( SPAN, FormalParameterKind::FormalParameter, - self.ast.new_vec_single(self.ast.formal_parameter( - SPAN, - self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, arg_name)), + self.ctx.ast.new_vec_single( + self.ctx.ast.formal_parameter( + SPAN, + self.ctx.ast.binding_pattern( + self.ctx + .ast + .binding_pattern_identifier(BindingIdentifier::new(SPAN, arg_name)), + None, + false, + ), None, false, + false, + self.ctx.ast.new_vec(), ), - None, - false, - false, - self.ast.new_vec(), - )), + ), None, ); - let function = self.ast.function( + let function = self.ctx.ast.function( FunctionType::FunctionExpression, SPAN, None, @@ -688,36 +709,39 @@ impl<'a> TypeScript<'a> { None, Modifiers::empty(), ); - let function_expr = self.ast.function_expression(function); - self.ast.parenthesized_expression(SPAN, function_expr) + let function_expr = self.ctx.ast.function_expression(function); + self.ctx.ast.parenthesized_expression(SPAN, function_expr) }; - let arguments = { - let right = { - let left = self.ast.simple_assignment_target_identifier(IdentifierReference::new( - SPAN, - name.clone(), - )); - let right = self.ast.object_expression(SPAN, self.ast.new_vec(), None); - self.ast.parenthesized_expression( - SPAN, - self.ast.assignment_expression(SPAN, AssignmentOperator::Assign, left, right), - ) - }; - self.ast.new_vec_single(Argument::Expression( - self.ast.logical_expression( + let arguments = + { + let right = { + let left = self.ctx.ast.simple_assignment_target_identifier( + IdentifierReference::new(SPAN, name.clone()), + ); + let right = self.ctx.ast.object_expression(SPAN, self.ctx.ast.new_vec(), None); + self.ctx.ast.parenthesized_expression( + SPAN, + self.ctx.ast.assignment_expression( + SPAN, + AssignmentOperator::Assign, + left, + right, + ), + ) + }; + self.ctx.ast.new_vec_single(Argument::Expression(self.ctx.ast.logical_expression( SPAN, - self.ast.identifier_reference_expression(IdentifierReference::new( + self.ctx.ast.identifier_reference_expression(IdentifierReference::new( SPAN, name.clone(), )), LogicalOperator::Or, right, - ), - )) - }; - let expr = self.ast.call_expression(SPAN, callee, arguments, false, None); - self.ast.expression_statement(SPAN, expr) + ))) + }; + let expr = self.ctx.ast.call_expression(SPAN, callee, arguments, false, None); + self.ctx.ast.expression_statement(SPAN, expr) } /// Transform constructor method @@ -761,20 +785,26 @@ impl<'a> TypeScript<'a> { for name in params_name { // TODO: We should push it before the super call - body.statements.push(self.ast.expression_statement( - SPAN, - self.ast.assignment_expression( + body.statements.push( + self.ctx.ast.expression_statement( SPAN, - AssignmentOperator::Assign, - self.ast.simple_assignment_target_member_expression(self.ast.static_member( + self.ctx.ast.assignment_expression( SPAN, - self.ast.this_expression(SPAN), - IdentifierName::new(SPAN, name.clone()), - false, - )), - self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)), + AssignmentOperator::Assign, + self.ctx.ast.simple_assignment_target_member_expression( + self.ctx.ast.static_member( + SPAN, + self.ctx.ast.this_expression(SPAN), + IdentifierName::new(SPAN, name.clone()), + false, + ), + ), + self.ctx + .ast + .identifier_reference_expression(IdentifierReference::new(SPAN, name)), + ), ), - )); + ); } } } From fa39fa87b3f54ffece7b6c7f4c737337bca122b4 Mon Sep 17 00:00:00 2001 From: Wang Wenzhe Date: Tue, 26 Mar 2024 21:24:04 +0800 Subject: [PATCH 4/8] feat(linter/tree-shaking): check CallExpression when called (#2809) --- .../listener_map.rs | 84 +++++++++++++++---- .../no_side_effects_in_initialization/mod.rs | 8 +- .../no_side_effects_in_initialization.snap | 6 ++ crates/oxc_linter/src/utils/tree_shaking.rs | 16 ++++ 4 files changed, 98 insertions(+), 16 deletions(-) diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs index 8e293f892d7a8..47f33e3fb5d6b 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs @@ -1,18 +1,24 @@ use std::cell::RefCell; -use oxc_ast::ast::{ - Argument, ArrayExpressionElement, AssignmentTarget, CallExpression, ComputedMemberExpression, - Expression, IdentifierReference, MemberExpression, PrivateFieldExpression, Program, - SimpleAssignmentTarget, Statement, StaticMemberExpression, +use oxc_ast::{ + ast::{ + Argument, ArrayExpressionElement, AssignmentTarget, CallExpression, + ComputedMemberExpression, Expression, IdentifierReference, MemberExpression, + PrivateFieldExpression, Program, SimpleAssignmentTarget, Statement, StaticMemberExpression, + }, + AstKind, }; -use oxc_semantic::SymbolId; +use oxc_semantic::{AstNode, SymbolId}; use oxc_span::GetSpan; use rustc_hash::FxHashSet; -use crate::{ast_util::get_symbol_id_of_variable, utils::Value, LintContext}; +use crate::{ + ast_util::{get_declaration_of_variable, get_symbol_id_of_variable}, + utils::{get_write_expr, Value}, + LintContext, +}; use super::NoSideEffectsDiagnostic; - pub struct NodeListenerOptions<'a, 'b> { checked_mutated_nodes: RefCell>, ctx: &'b LintContext<'a>, @@ -54,6 +60,23 @@ impl<'a> ListenerMap for Statement<'a> { } } +// we don't need implement all AstNode +// it's same as `reportSideEffectsInDefinitionWhenCalled` in eslint-plugin-tree-shaking +// +impl<'a> ListenerMap for AstNode<'a> { + fn report_effects_when_called(&self, options: &NodeListenerOptions) { + #[allow(clippy::single_match)] + match self.kind() { + AstKind::VariableDeclarator(decl) => { + if let Some(init) = &decl.init { + init.report_effects_when_called(options); + } + } + _ => {} + } + } +} + impl<'a> ListenerMap for Expression<'a> { fn report_effects(&self, options: &NodeListenerOptions) { match self { @@ -79,7 +102,10 @@ impl<'a> ListenerMap for Expression<'a> { Self::Identifier(ident) => { ident.report_effects_when_mutated(options); } - _ => {} + _ => { + // Default behavior + options.ctx.diagnostic(NoSideEffectsDiagnostic::Mutation(self.span())); + } } } fn report_effects_when_called(&self, options: &NodeListenerOptions) { @@ -90,7 +116,10 @@ impl<'a> ListenerMap for Expression<'a> { Self::Identifier(expr) => { expr.report_effects_when_called(options); } - _ => {} + _ => { + // Default behavior + options.ctx.diagnostic(NoSideEffectsDiagnostic::Call(self.span())); + } } } } @@ -120,9 +149,18 @@ impl<'a> ListenerMap for CallExpression<'a> { } } fn report_effects_when_called(&self, options: &NodeListenerOptions) { + let ctx = options.ctx; if let Expression::Identifier(ident) = &self.callee { - if get_symbol_id_of_variable(ident, options.ctx).is_none() { - // TODO: Not work now + if let Some(node) = get_declaration_of_variable(ident, ctx) { + let Some(parent) = ctx.nodes().parent_kind(node.id()) else { + return; + }; + // TODO: `isLocalVariableAWhitelistedModule` + if matches!(parent, AstKind::ImportDeclaration(_)) { + return; + } + options.ctx.diagnostic(NoSideEffectsDiagnostic::CallReturnValue(self.span)); + } else { options.ctx.diagnostic(NoSideEffectsDiagnostic::CallReturnValue(self.span)); } } @@ -185,7 +223,20 @@ impl<'a> ListenerMap for IdentifierReference<'a> { fn report_effects_when_called(&self, options: &NodeListenerOptions) { let ctx = options.ctx; - if get_symbol_id_of_variable(self, ctx).is_none() { + if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) { + let symbol_table = ctx.semantic().symbols(); + for reference in symbol_table.get_resolved_references(symbol_id) { + if reference.is_write() { + let node_id = reference.node_id(); + if let Some(expr) = get_write_expr(node_id, ctx) { + expr.report_effects_when_called(options); + } + } + } + let symbol_table = ctx.semantic().symbols(); + let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id)); + node.report_effects_when_called(options); + } else { ctx.diagnostic(NoSideEffectsDiagnostic::CallGlobal( self.name.to_compact_str(), self.span, @@ -199,7 +250,12 @@ impl<'a> ListenerMap for IdentifierReference<'a> { if options.insert_mutated_node(symbol_id) { for reference in ctx.symbols().get_resolved_references(symbol_id) { if reference.is_write() { - ctx.diagnostic(NoSideEffectsDiagnostic::Mutation( + let node_id = reference.node_id(); + if let Some(expr) = get_write_expr(node_id, ctx) { + expr.report_effects_when_mutated(options); + } + + ctx.diagnostic(NoSideEffectsDiagnostic::MutationWithName( self.name.to_compact_str(), self.span, )); @@ -207,7 +263,7 @@ impl<'a> ListenerMap for IdentifierReference<'a> { } } } else { - ctx.diagnostic(NoSideEffectsDiagnostic::Mutation( + ctx.diagnostic(NoSideEffectsDiagnostic::MutationWithName( self.name.to_compact_str(), self.span, )); diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs index 19ae0e67db497..c716cc32446ae 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs @@ -18,9 +18,13 @@ enum NoSideEffectsDiagnostic { #[diagnostic(severity(warning))] Assignment(CompactStr, #[label] Span), + #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating")] + #[diagnostic(severity(warning))] + Mutation(#[label] Span), + #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating `{0}`")] #[diagnostic(severity(warning))] - Mutation(CompactStr, #[label] Span), + MutationWithName(CompactStr, #[label] Span), #[error("eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of mutating function return value")] #[diagnostic(severity(warning))] @@ -387,7 +391,7 @@ fn test() { // "(()=>{})(ext(), 1)", // "(()=>{})(1, ext())", // // CallExpression when called - // "const x = ()=>ext; const y = x(); y()", + "const x = ()=>ext; const y = x(); y()", // // CallExpression when mutated // "const x = ()=>ext; const y = x(); y.z = 1", // // CatchClause diff --git a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap index 664174820f882..216c9820b934f 100644 --- a/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap +++ b/crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap @@ -25,3 +25,9 @@ expression: no_side_effects_in_initialization 1 │ const x = {};x[ext()] = 1 · ─── ╰──── + + ⚠ eslint-plugin-tree-shaking(no-side-effects-in-initialization): Cannot determine side-effects of calling function return value + ╭─[no_side_effects_in_initialization.tsx:1:30] + 1 │ const x = ()=>ext; const y = x(); y() + · ─── + ╰──── diff --git a/crates/oxc_linter/src/utils/tree_shaking.rs b/crates/oxc_linter/src/utils/tree_shaking.rs index 3cba28a1484bb..31e1e1ceae296 100644 --- a/crates/oxc_linter/src/utils/tree_shaking.rs +++ b/crates/oxc_linter/src/utils/tree_shaking.rs @@ -1,5 +1,21 @@ +use oxc_ast::{ast::Expression, AstKind}; +use oxc_semantic::AstNodeId; + +use crate::LintContext; + #[allow(dead_code)] pub enum Value { Boolean(bool), Number(f64), } + +pub fn get_write_expr<'a, 'b>( + node_id: AstNodeId, + ctx: &'b LintContext<'a>, +) -> Option<&'b Expression<'a>> { + let parent = ctx.nodes().parent_kind(node_id)?; + match parent { + AstKind::AssignmentExpression(assign_expr) => Some(&assign_expr.right), + _ => None, + } +} From 3897cf411887daa2657d2ebf6c188c1866d5adba Mon Sep 17 00:00:00 2001 From: Wang Wenzhe Date: Tue, 26 Mar 2024 21:32:29 +0800 Subject: [PATCH 5/8] chore(eslint/tree-shaking): add `NoEffect` explicitly (#2823) --- .../listener_map.rs | 34 +++++++++++++++---- crates/oxc_linter/src/utils/tree_shaking.rs | 2 ++ tasks/benchmark/Cargo.toml | 20 +++++------ 3 files changed, 39 insertions(+), 17 deletions(-) diff --git a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs index 47f33e3fb5d6b..24192a79b0327 100644 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs +++ b/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs @@ -4,7 +4,8 @@ use oxc_ast::{ ast::{ Argument, ArrayExpressionElement, AssignmentTarget, CallExpression, ComputedMemberExpression, Expression, IdentifierReference, MemberExpression, - PrivateFieldExpression, Program, SimpleAssignmentTarget, Statement, StaticMemberExpression, + ModuleDeclaration, PrivateFieldExpression, Program, SimpleAssignmentTarget, Statement, + StaticMemberExpression, }, AstKind, }; @@ -14,7 +15,7 @@ use rustc_hash::FxHashSet; use crate::{ ast_util::{get_declaration_of_variable, get_symbol_id_of_variable}, - utils::{get_write_expr, Value}, + utils::{get_write_expr, no_effects, Value}, LintContext, }; @@ -54,8 +55,23 @@ impl<'a> ListenerMap for Program<'a> { impl<'a> ListenerMap for Statement<'a> { fn report_effects(&self, options: &NodeListenerOptions) { - if let Self::ExpressionStatement(expr_stmt) = self { - expr_stmt.expression.report_effects(options); + match self { + Self::ExpressionStatement(expr_stmt) => { + expr_stmt.expression.report_effects(options); + } + Self::BreakStatement(_) | Self::ContinueStatement(_) | Self::EmptyStatement(_) => { + no_effects(); + } + Self::ModuleDeclaration(decl) => { + if matches!( + decl.0, + ModuleDeclaration::ExportAllDeclaration(_) + | ModuleDeclaration::ImportDeclaration(_) + ) { + no_effects(); + } + } + _ => {} } } } @@ -87,12 +103,15 @@ impl<'a> ListenerMap for Expression<'a> { assign_expr.left.report_effects_when_assigned(options); assign_expr.right.report_effects(options); } - Self::Identifier(ident) => { - ident.report_effects(options); - } Self::CallExpression(call_expr) => { call_expr.report_effects(options); } + Self::ArrowFunctionExpression(_) + | Self::FunctionExpression(_) + | Self::Identifier(_) + | Self::MetaProperty(_) + | Self::Super(_) + | Self::ThisExpression(_) => no_effects(), _ => {} } } @@ -102,6 +121,7 @@ impl<'a> ListenerMap for Expression<'a> { Self::Identifier(ident) => { ident.report_effects_when_mutated(options); } + Self::ArrowFunctionExpression(_) | Self::ObjectExpression(_) => no_effects(), _ => { // Default behavior options.ctx.diagnostic(NoSideEffectsDiagnostic::Mutation(self.span())); diff --git a/crates/oxc_linter/src/utils/tree_shaking.rs b/crates/oxc_linter/src/utils/tree_shaking.rs index 31e1e1ceae296..043fac7b9e57c 100644 --- a/crates/oxc_linter/src/utils/tree_shaking.rs +++ b/crates/oxc_linter/src/utils/tree_shaking.rs @@ -19,3 +19,5 @@ pub fn get_write_expr<'a, 'b>( _ => None, } } + +pub fn no_effects() {} diff --git a/tasks/benchmark/Cargo.toml b/tasks/benchmark/Cargo.toml index 197653c670741..5a37c8905166d 100644 --- a/tasks/benchmark/Cargo.toml +++ b/tasks/benchmark/Cargo.toml @@ -78,16 +78,16 @@ serde_json = { workspace = true, optional = true } [features] default = [ - "dep:oxc_allocator", - "dep:oxc_linter", - "dep:oxc_minifier", - "dep:oxc_parser", - "dep:oxc_prettier", - "dep:oxc_semantic", - "dep:oxc_span", - "dep:oxc_tasks_common", - "dep:oxc_transformer", - "dep:oxc_codegen", + "dep:oxc_allocator", + "dep:oxc_linter", + "dep:oxc_minifier", + "dep:oxc_parser", + "dep:oxc_prettier", + "dep:oxc_semantic", + "dep:oxc_span", + "dep:oxc_tasks_common", + "dep:oxc_transformer", + "dep:oxc_codegen", ] codspeed = ["criterion/codspeed"] codspeed_napi = ["criterion/codspeed", "dep:serde", "dep:serde_json"] From 881329dc1aa480f2b48c9a133955fec583fb9272 Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Tue, 26 Mar 2024 14:40:49 +0000 Subject: [PATCH 6/8] chore: remove cargo-machete package metadata (#2824) `cargo-machete` has been replaced with `cargo-shear`, so the package metadata for `cargo-machete` is no longer required. --- crates/oxc_linter/Cargo.toml | 3 --- crates/oxc_minifier/Cargo.toml | 3 --- napi/parser/Cargo.toml | 3 --- 3 files changed, 9 deletions(-) diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index d9fa81b973585..606ddae6846c5 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -52,6 +52,3 @@ json-strip-comments = "1.0.2" [dev-dependencies] insta = { workspace = true } - -[package.metadata.cargo-machete] -ignored = ["once_cell"] diff --git a/crates/oxc_minifier/Cargo.toml b/crates/oxc_minifier/Cargo.toml index 025b62a4542a4..3cd2397ab9119 100644 --- a/crates/oxc_minifier/Cargo.toml +++ b/crates/oxc_minifier/Cargo.toml @@ -38,6 +38,3 @@ oxc_codegen = { workspace = true } insta = { workspace = true } walkdir = { workspace = true } pico-args = { workspace = true } - -[package.metadata.cargo-machete] -ignored = ["insta", "walkdir"] diff --git a/napi/parser/Cargo.toml b/napi/parser/Cargo.toml index 08058e9397117..6aff0b853c3cb 100644 --- a/napi/parser/Cargo.toml +++ b/napi/parser/Cargo.toml @@ -38,6 +38,3 @@ napi-derive = { workspace = true } [build-dependencies] napi-build = "2" - -[package.metadata.cargo-machete] -ignored = ["napi_build"] From 95fc28168cd86bbc05ec8aef6b52d4ba095e3a05 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 26 Mar 2024 23:57:50 +0800 Subject: [PATCH 7/8] chore: apply `cargo autoinherit` (#2826) See https://github.com/mainmatter/cargo-autoinherit --- Cargo.toml | 129 +++++++++++++++----------- crates/oxc_codegen/Cargo.toml | 4 +- crates/oxc_diagnostics/Cargo.toml | 6 +- crates/oxc_language_server/Cargo.toml | 6 +- crates/oxc_linter/Cargo.toml | 10 +- crates/oxc_parser/Cargo.toml | 4 +- crates/oxc_semantic/Cargo.toml | 4 +- crates/oxc_span/Cargo.toml | 2 +- justfile | 19 +++- napi/parser/Cargo.toml | 4 +- tasks/common/Cargo.toml | 6 +- tasks/coverage/Cargo.toml | 10 +- tasks/minsize/Cargo.toml | 4 +- 13 files changed, 122 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0b5f508a0bbef..19165c062a3b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,59 +85,84 @@ oxc_linter = { path = "crates/oxc_linter" } oxc_prettier = { path = "crates/oxc_prettier" } oxc_tasks_common = { path = "tasks/common" } -napi = { version = "2" } -napi-derive = { version = "2" } +napi = "2" +napi-derive = "2" -assert-unchecked = { version = "0.1.2" } -bpaf = { version = "0.9.11" } -bitflags = { version = "2.5.0" } -bumpalo = { version = "3.15.4" } -convert_case = { version = "0.6.0" } -dashmap = { version = "5.5.3" } -flate2 = { version = "1.0.28" } -futures = { version = "0.3.30" } -glob = { version = "0.3.1" } -ignore = { version = "0.4.22" } -itertools = { version = "0.12.1" } -jemallocator = { version = "0.5.4" } -lazy_static = { version = "1.4.0" } -miette = { version = "7.2.0", features = ["fancy-no-syscall"] } -mimalloc = { version = "0.1.39" } -num-bigint = { version = "0.4.4" } -num-traits = { version = "0.2.18" } -phf = { version = "0.11" } -pico-args = { version = "0.5.0" } -proc-macro2 = { version = "1.0.79" } -project-root = { version = "0.2.2" } -quote = { version = "1.0.35" } -rayon = { version = "1.10.0" } -regex = { version = "1.10.4" } -rustc-hash = { version = "1.1.0", default-features = false, features = ["std"] } -ryu-js = { version = "1.0.1" } -ropey = { version = "1.6.1" } -seq-macro = { version = "0.3.5" } -serde = { version = "1.0.197" } -serde_json = { version = "1.0.114" } -syn = { version = "=1.0.109" } -tempfile = { version = "3.10.1" } -thiserror = { version = "1.0.58" } -tokio = { version = "1" } -tower-lsp = { version = "0.20.0", features = ["proposed"] } -unicode-id-start = { version = "1.1.2" } -ureq = { version = "2.9.6", default-features = false, features = ["tls", "json"] } -url = { version = "2.5.0" } -walkdir = { version = "2.5.0" } -indexmap = { version = "2.2.6" } -index_vec = { version = "0.1.3" } -static_assertions = { version = "1.1.0" } -tracing-subscriber = { version = "0.3" } -insta = { version = "1.36.1", features = ["glob"] } -mime_guess = { version = "2.0.4" } -language-tags = { version = "0.3.2" } -tsify = { version = "0.4.5" } -wasm-bindgen = { version = "0.2" } -serde-wasm-bindgen = { version = "0.6.5" } -handlebars = { version = "5.1.2" } +assert-unchecked = "0.1.2" +bpaf = "0.9.11" +bitflags = "2.5.0" +bumpalo = "3.15.4" +convert_case = "0.6.0" +dashmap = "5.5.3" +flate2 = "1.0.28" +futures = "0.3.30" +glob = "0.3.1" +ignore = "0.4.22" +itertools = "0.12.1" +jemallocator = "0.5.4" +lazy_static = "1.4.0" +miette = { version = "7.2.0", features = ["fancy-no-syscall"] } +mimalloc = "0.1.39" +num-bigint = "0.4.4" +num-traits = "0.2.18" +phf = "0.11" +pico-args = "0.5.0" +proc-macro2 = "1.0.79" +project-root = "0.2.2" +quote = "1.0.35" +rayon = "1.10.0" +regex = "1.10.4" +rustc-hash = "1.1.0" +ryu-js = "1.0.1" +ropey = "1.6.1" +seq-macro = "0.3.5" +serde = "1.0.197" +serde_json = "1.0.114" +syn = "=1.0.109" +tempfile = "3.10.1" +thiserror = "1.0.58" +tokio = "1" +tower-lsp = "0.20.0" +unicode-id-start = "1.1.2" +ureq = { version = "2.9.6", default-features = false } +url = "2.5.0" +walkdir = "2.5.0" +indexmap = "2.2.6" +index_vec = "0.1.3" +static_assertions = "1.1.0" +tracing-subscriber = "0.3" +insta = "1.36.1" +mime_guess = "2.0.4" +language-tags = "0.3.2" +tsify = "0.4.5" +wasm-bindgen = "0.2" +serde-wasm-bindgen = "0.6.5" +handlebars = "5.1.2" +base64 = "0.22.0" +brotlic = "0.8.2" +compact_str = "0.7.1" +console = "0.15.8" +encoding_rs = "0.8.33" +encoding_rs_io = "0.1.7" +env_logger = { version = "0.11.3", default-features = false } +flexbuffers = "2.0.0" +globset = "0.4.14" +humansize = "2.1.3" +json-strip-comments = "1.0.2" +log = "0.4.21" +memchr = "2.7.1" +napi-build = "2" +once_cell = "1.19.0" +ouroboros = "0.18.3" +owo-colors = "4.0.0" +oxc_resolver = "1.6.3" +petgraph = "0.6.4" +rust-lapper = "1.1.0" +serde_yaml = "0.9.34" +similar = "2.4.0" +sourcemap = "8.0.0" +textwrap = "0.16.0" +unicode-width = "0.1.11" [profile.dev] debug = 1 # "limited" debug, speed up compilation; debug info without type or variable-level information. diff --git a/crates/oxc_codegen/Cargo.toml b/crates/oxc_codegen/Cargo.toml index 41965d5b759e2..12c783938a19b 100644 --- a/crates/oxc_codegen/Cargo.toml +++ b/crates/oxc_codegen/Cargo.toml @@ -23,10 +23,10 @@ oxc_ast = { workspace = true } oxc_span = { workspace = true } oxc_allocator = { workspace = true } oxc_syntax = { workspace = true } -sourcemap = { version = "8.0.0" } +sourcemap = { workspace = true } bitflags = { workspace = true } rustc-hash = { workspace = true } [dev-dependencies] oxc_parser = { workspace = true } -base64 = "0.22.0" +base64 = { workspace = true } diff --git a/crates/oxc_diagnostics/Cargo.toml b/crates/oxc_diagnostics/Cargo.toml index 4af8d255e85d2..8d0b2fba42a66 100644 --- a/crates/oxc_diagnostics/Cargo.toml +++ b/crates/oxc_diagnostics/Cargo.toml @@ -21,6 +21,6 @@ doctest = false thiserror = { workspace = true } miette = { workspace = true } -unicode-width = "0.1.11" -owo-colors = { version = "4.0.0" } -textwrap = { version = "0.16.0" } +unicode-width = { workspace = true } +owo-colors = { workspace = true } +textwrap = { workspace = true } diff --git a/crates/oxc_language_server/Cargo.toml b/crates/oxc_language_server/Cargo.toml index a9fbec1ddd93c..224f9b5718d1e 100644 --- a/crates/oxc_language_server/Cargo.toml +++ b/crates/oxc_language_server/Cargo.toml @@ -34,6 +34,6 @@ tokio = { workspace = true, features = ["full"] } tower-lsp = { workspace = true, features = ["proposed"] } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -log = "0.4.21" -globset = "0.4.14" -env_logger = { version = "0.11.3", default-features = false, features = ["humantime"] } +log = { workspace = true } +globset = { workspace = true } +env_logger = { workspace = true, features = ["humantime"] } diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index 606ddae6846c5..033015d7e6008 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -29,7 +29,7 @@ oxc_semantic = { workspace = true } oxc_syntax = { workspace = true } oxc_codegen = { workspace = true } oxc_index = { workspace = true } -oxc_resolver = { version = "1.6.3" } +oxc_resolver = { workspace = true } rayon = { workspace = true } lazy_static = { workspace = true } # used in oxc_macros @@ -45,10 +45,10 @@ language-tags = { workspace = true } mime_guess = { workspace = true } url = { workspace = true } -rust-lapper = "1.1.0" -once_cell = "1.19.0" -memchr = "2.7.1" -json-strip-comments = "1.0.2" +rust-lapper = { workspace = true } +once_cell = { workspace = true } +memchr = { workspace = true } +json-strip-comments = { workspace = true } [dev-dependencies] insta = { workspace = true } diff --git a/crates/oxc_parser/Cargo.toml b/crates/oxc_parser/Cargo.toml index 832e0bef71c4c..c3227f1d2edab 100644 --- a/crates/oxc_parser/Cargo.toml +++ b/crates/oxc_parser/Cargo.toml @@ -31,12 +31,12 @@ rustc-hash = { workspace = true } num-bigint = { workspace = true } seq-macro = { workspace = true } -memchr = "2.7.1" +memchr = { workspace = true } [dev-dependencies] oxc_ast = { workspace = true, features = ["serialize"] } serde_json = { workspace = true } -ouroboros = "0.18.3" # for `multi-thread` example +ouroboros = { workspace = true } # for `multi-thread` example [features] # Expose Lexer for benchmarks diff --git a/crates/oxc_semantic/Cargo.toml b/crates/oxc_semantic/Cargo.toml index 4db12a9212b55..adaceb3caf8e0 100644 --- a/crates/oxc_semantic/Cargo.toml +++ b/crates/oxc_semantic/Cargo.toml @@ -30,7 +30,7 @@ indexmap = { workspace = true } phf = { workspace = true, features = ["macros"] } rustc-hash = { workspace = true } serde = { workspace = true, features = ["derive"], optional = true } -petgraph = "0.6.4" +petgraph = { workspace = true } tsify = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true } @@ -40,7 +40,7 @@ oxc_parser = { workspace = true } itertools = { workspace = true } indexmap = { workspace = true } -insta = { workspace = true } +insta = { workspace = true, features = ["glob"] } phf = { workspace = true, features = ["macros"] } rustc-hash = { workspace = true } diff --git a/crates/oxc_span/Cargo.toml b/crates/oxc_span/Cargo.toml index 54ef475badd47..d06a4790664e7 100644 --- a/crates/oxc_span/Cargo.toml +++ b/crates/oxc_span/Cargo.toml @@ -20,7 +20,7 @@ doctest = false [dependencies] miette = { workspace = true } -compact_str = { version = "0.7.1" } +compact_str = { workspace = true } tsify = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true } diff --git a/justfile b/justfile index 254d82955e7d1..cbbac91749c51 100755 --- a/justfile +++ b/justfile @@ -53,10 +53,6 @@ check: test: cargo test -test-transform: - cargo run -p oxc_transform_conformance - cargo run -p oxc_transform_conformance -- --exec - # Lint the whole project lint: cargo lint -- --deny warnings @@ -76,6 +72,21 @@ codecov: benchmark: cargo benchmark +# Removed Unused Dependencies +shear: + cargo binstall cargo-shear + cargo shear --fix + +# Automatically DRY up Cargo.toml manifests in a workspace. +autoinherit: + cargo binstall cargo-autoinherit + cargo autoinherit + +# Test Transform +test-transform: + cargo run -p oxc_transform_conformance + cargo run -p oxc_transform_conformance -- --exec + # Generate the JavaScript global variables. See `tasks/javascript_globals` javascript-globals: cargo run -p javascript_globals diff --git a/napi/parser/Cargo.toml b/napi/parser/Cargo.toml index 6aff0b853c3cb..e28d3a8695f65 100644 --- a/napi/parser/Cargo.toml +++ b/napi/parser/Cargo.toml @@ -30,11 +30,11 @@ oxc_module_lexer = { path = "../../crates/oxc_module_lexer" } serde = { workspace = true } serde_json = { workspace = true } -flexbuffers = { version = "2.0.0" } +flexbuffers = { workspace = true } tokio = { workspace = true } napi = { workspace = true, features = ["serde-json", "async"] } napi-derive = { workspace = true } [build-dependencies] -napi-build = "2" +napi-build = { workspace = true } diff --git a/tasks/common/Cargo.toml b/tasks/common/Cargo.toml index f9c2cc1f240da..03338ccea2068 100644 --- a/tasks/common/Cargo.toml +++ b/tasks/common/Cargo.toml @@ -13,13 +13,13 @@ test = false doctest = false [dependencies] -console = "0.15.8" +console = { workspace = true } oxc_syntax = { workspace = true, features = ["serialize"] } project-root = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } -similar = "2.4.0" +similar = { workspace = true } -ureq = { workspace = true } +ureq = { workspace = true, features = ["tls", "json"] } url = { workspace = true } diff --git a/tasks/coverage/Cargo.toml b/tasks/coverage/Cargo.toml index ab9933d27105d..2a84bca8faa7d 100644 --- a/tasks/coverage/Cargo.toml +++ b/tasks/coverage/Cargo.toml @@ -44,8 +44,8 @@ phf = { workspace = true, features = ["macros"] } futures = { workspace = true } tokio = { workspace = true, features = ["rt-multi-thread", "macros"] } -console = "0.15.8" -encoding_rs = "0.8.33" -encoding_rs_io = "0.1.7" -serde_yaml = "0.9.34" -similar = "2.4.0" +console = { workspace = true } +encoding_rs = { workspace = true } +encoding_rs_io = { workspace = true } +serde_yaml = { workspace = true } +similar = { workspace = true } diff --git a/tasks/minsize/Cargo.toml b/tasks/minsize/Cargo.toml index b1640b4ef838d..b9c12a591117d 100644 --- a/tasks/minsize/Cargo.toml +++ b/tasks/minsize/Cargo.toml @@ -25,5 +25,5 @@ oxc_minifier = { workspace = true } oxc_tasks_common = { workspace = true } flate2 = { workspace = true } -humansize = "2.1.3" -brotlic = "0.8.2" +humansize = { workspace = true } +brotlic = { workspace = true } From 8c6936ab7452d50b929a20fbe03fa5187fa79bbd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Mar 2024 16:04:53 +0000 Subject: [PATCH 8/8] chore(deps): lock file maintenance rust crates (#2827) --- Cargo.lock | 46 ++++++++++++++++++---------------------------- Cargo.toml | 4 ++-- 2 files changed, 20 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cebbe4e5e0d72..7b85a51520e2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,9 +74,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backtrace" @@ -274,9 +274,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", ] @@ -878,9 +878,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.36.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +checksum = "1718b3f2b85bb5054baf8ce406e36401f27c3169205f4175504c4b1d98252d3f" dependencies = [ "console", "globset", @@ -888,7 +888,6 @@ dependencies = [ "linked-hash-map", "similar", "walkdir", - "yaml-rust", ] [[package]] @@ -908,9 +907,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "javascript_globals" @@ -1129,9 +1128,9 @@ dependencies = [ [[package]] name = "napi" -version = "2.16.0" +version = "2.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54a63d0570e4c3e0daf7a8d380563610e159f538e20448d6c911337246f40e84" +checksum = "c4ca998356d8ff9fba7a070dae4508a2298439c98c9f3bc9c07669538b999e8f" dependencies = [ "bitflags 2.5.0", "ctor", @@ -1151,9 +1150,9 @@ checksum = "2f9130fccc5f763cf2069b34a089a18f0d0883c66aceb81f2fad541a3d823c43" [[package]] name = "napi-derive" -version = "2.16.0" +version = "2.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05bb7c37e3c1dda9312fdbe4a9fc7507fca72288ba154ec093e2d49114e727ce" +checksum = "b138cecf1141ae0ff5d62f4aa0e2f269aec339f66070f346ba6fb4279f1fc178" dependencies = [ "cfg-if", "convert_case", @@ -1165,9 +1164,9 @@ dependencies = [ [[package]] name = "napi-derive-backend" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f785a8b8d7b83e925f5aa6d2ae3c159d17fe137ac368dc185bef410e7acdaeb4" +checksum = "ce5126b64f6ad9e28e30e6d15213dd378626b38f556454afebc42f7f02a90902" dependencies = [ "convert_case", "once_cell", @@ -2208,9 +2207,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.2" +version = "0.22.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41" +checksum = "99008d7ad0bbbea527ec27bddbc0e432c5b87d8175178cee68d2eec9c4a1813c" dependencies = [ "log", "ring", @@ -2344,9 +2343,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "indexmap", "itoa", @@ -3233,15 +3232,6 @@ dependencies = [ "tap", ] -[[package]] -name = "yaml-rust" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" -dependencies = [ - "linked-hash-map", -] - [[package]] name = "yansi" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index 19165c062a3b7..7b48f020df79c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -117,7 +117,7 @@ ryu-js = "1.0.1" ropey = "1.6.1" seq-macro = "0.3.5" serde = "1.0.197" -serde_json = "1.0.114" +serde_json = "1.0.115" syn = "=1.0.109" tempfile = "3.10.1" thiserror = "1.0.58" @@ -131,7 +131,7 @@ indexmap = "2.2.6" index_vec = "0.1.3" static_assertions = "1.1.0" tracing-subscriber = "0.3" -insta = "1.36.1" +insta = "1.37.0" mime_guess = "2.0.4" language-tags = "0.3.2" tsify = "0.4.5"