From f4213b8d12ae23c539001990b8a1f70483fa6e8b Mon Sep 17 00:00:00 2001 From: overlookmotel Date: Fri, 15 Nov 2024 16:02:54 +0000 Subject: [PATCH 001/121] fix(tools): `just test-transform` run conformance only once (#7295) `--exec` flag also runs the non-exec tests, so it's not required to run it twice. --- justfile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/justfile b/justfile index 578ffb79b0a6cd..a3352e17604148 100755 --- a/justfile +++ b/justfile @@ -128,8 +128,7 @@ autoinherit: # Test Transform test-transform *args='': - cargo run -p oxc_transform_conformance -- {{args}} - cargo run -p oxc_transform_conformance -- --exec {{args}} + cargo run -p oxc_transform_conformance -- --exec {{args}} # Install wasm-pack install-wasm: From 16cfb96a796564b65783d2e2d3f60f451fd64e69 Mon Sep 17 00:00:00 2001 From: dalaoshu Date: Sat, 16 Nov 2024 00:03:23 +0800 Subject: [PATCH 002/121] fix(justfile): make submodules work on windows (#7293) Related to #7290, closes #7296 By default, `Windows` encounters the following issue unless the user installs `PowerShell 7` (pwsh). ```bash error: Recipe `submodules` could not be run because just could not find the shell: program not found error: Recipe `init` could not be run because just could not find the shell: program not found ``` Furthermore, I have found a better way to solve this problem. --- justfile | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/justfile b/justfile index a3352e17604148..9419c85c696c2c 100755 --- a/justfile +++ b/justfile @@ -1,6 +1,6 @@ #!/usr/bin/env -S just --justfile -set windows-shell := ["pwsh", "-NoLogo", "-Command"] +set windows-shell := ["powershell.exe", "-NoLogo", "-Command"] set shell := ["bash", "-cu"] _default: @@ -191,18 +191,17 @@ new-vitest-rule name: new-security-rule name: cargo run -p rulegen {{name}} security -clone-submodule dir url sha: - just git-init-if-not-exist {{dir}} - cd {{dir}} && git remote add origin {{url}} - cd {{dir}} && git fetch --depth=1 origin {{sha}} && git reset --hard {{sha}} - [unix] -git-init-if-not-exist dir: +clone-submodule dir url sha: cd {{dir}} || git init {{dir}} + cd {{dir}} && git remote add origin {{url}} || true + cd {{dir}} && git fetch --depth=1 origin {{sha}} && git reset --hard {{sha}} [windows] -git-init-if-not-exist dir: - if (Test-Path {{ dir }}) {cd {{ dir }}} else {git init {{dir}}} +clone-submodule dir url sha: + if (-not (Test-Path {{dir}}/.git)) { git init {{dir}} } + cd {{dir}} ; if ((git remote) -notcontains 'origin') { git remote add origin {{url}} } else { git remote set-url origin {{url}} } + cd {{dir}} ; git fetch --depth=1 origin {{sha}} ; git reset --hard {{sha}} website path: cargo run -p website -- linter-rules --table {{path}}/src/docs/guide/usage/linter/generated-rules.md --rule-docs {{path}}/src/docs/guide/usage/linter/rules From a0766e6a7ff55c88f989c68ffe20df1a25ad1d9a Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:04:02 +0000 Subject: [PATCH 003/121] fix(codegen): fix arithmetic overflow printing unspanned nodes (#7292) Similar to #7289. Check if `span.end` is 0 before doing `span.end - 1`, to prevent arithmetic overflow. Also changed all checks to `span.end > 0`, just for consistency. --- crates/oxc_codegen/src/gen.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 3568417077daf9..06b29c25748bcd 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -665,7 +665,7 @@ impl<'a> Gen for Function<'a> { impl<'a> Gen for FunctionBody<'a> { fn gen(&self, p: &mut Codegen, ctx: Context) { let span_end = self.span.end; - let comments_at_end = if !p.options.minify && span_end != 0 { + let comments_at_end = if !p.options.minify && span_end > 0 { p.get_statement_comments(span_end - 1) } else { None @@ -1985,7 +1985,7 @@ impl<'a> GenExpr for ImportExpression<'a> { } if has_comment { // Handle `/* comment */);` - if !p.print_expr_comments(self.span.end - 1) { + if self.span.end > 0 && !p.print_expr_comments(self.span.end - 1) { p.print_soft_newline(); } p.dedent(); @@ -2067,13 +2067,13 @@ impl<'a> GenExpr for NewExpression<'a> { p.print_str("new "); self.callee.print_expr(p, Precedence::New, Context::FORBID_CALL); p.print_ascii_byte(b'('); - let has_comment = (!self.span.is_unspanned() && p.has_comment(self.span.end - 1)) + let has_comment = (self.span.end > 0 && p.has_comment(self.span.end - 1)) || self.arguments.iter().any(|item| p.has_comment(item.span().start)); if has_comment { p.indent(); p.print_list_with_comments(&self.arguments, ctx); // Handle `/* comment */);` - if !p.print_expr_comments(self.span.end - 1) { + if self.span.end > 0 && !p.print_expr_comments(self.span.end - 1) { p.print_soft_newline(); } p.dedent(); From 1cbc624a8bf86cacfbf79725031f616b7f1d3343 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Fri, 15 Nov 2024 16:44:08 +0000 Subject: [PATCH 004/121] refactor(traverse)!: rename `TraverseCtx` methods for creating `IdentifierReference`s (#7300) `create_reference_id` was a confusing name, as it doesn't return a `ReferenceId`. Rename these methods to more clearly represent what they do. --- .../src/common/helper_loader.rs | 8 ++- .../src/common/module_imports.rs | 2 +- .../src/es2016/exponentiation_operator.rs | 69 ++++++++++--------- .../src/es2017/async_to_generator.rs | 10 ++- .../src/es2018/object_rest_spread.rs | 2 +- .../es2021/logical_assignment_operators.rs | 2 +- crates/oxc_transformer/src/jsx/refresh.rs | 4 +- crates/oxc_transformer/src/regexp/mod.rs | 2 +- crates/oxc_transformer/src/typescript/enum.rs | 4 +- .../src/context/bound_identifier.rs | 2 +- .../src/context/maybe_bound_identifier.rs | 2 +- crates/oxc_traverse/src/context/mod.rs | 14 ++-- 12 files changed, 67 insertions(+), 54 deletions(-) diff --git a/crates/oxc_transformer/src/common/helper_loader.rs b/crates/oxc_transformer/src/common/helper_loader.rs index 555491703b1749..0346c988765ff0 100644 --- a/crates/oxc_transformer/src/common/helper_loader.rs +++ b/crates/oxc_transformer/src/common/helper_loader.rs @@ -277,8 +277,12 @@ impl<'a> HelperLoaderStore<'a> { static HELPER_VAR: &str = "babelHelpers"; let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), HELPER_VAR); - let ident = - ctx.create_reference_id(SPAN, Atom::from(HELPER_VAR), symbol_id, ReferenceFlags::Read); + let ident = ctx.create_ident_reference( + SPAN, + Atom::from(HELPER_VAR), + symbol_id, + ReferenceFlags::Read, + ); let object = Expression::Identifier(ctx.alloc(ident)); let property = ctx.ast.identifier_name(SPAN, Atom::from(helper.name())); Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) diff --git a/crates/oxc_transformer/src/common/module_imports.rs b/crates/oxc_transformer/src/common/module_imports.rs index 96d66e0e85b561..055849832c546a 100644 --- a/crates/oxc_transformer/src/common/module_imports.rs +++ b/crates/oxc_transformer/src/common/module_imports.rs @@ -227,7 +227,7 @@ impl<'a> ModuleImportsStore<'a> { ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let var_kind = VariableDeclarationKind::Var; - let ident = ctx.create_reference_id( + let ident = ctx.create_ident_reference( SPAN, Atom::from("require"), require_symbol_id, diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index d489405afb257c..2d787d592135b2 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -155,31 +155,30 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { // Make sure side-effects of evaluating `left` only happen once let reference = ctx.scoping.symbols_mut().get_reference_mut(ident.reference_id()); - let pow_left = - if let Some(symbol_id) = reference.symbol_id() { - // This variable is declared in scope so evaluating it multiple times can't trigger a getter. - // No need for a temp var. - // `left **= right` is being transformed to `left = Math.pow(left, right)`, - // so if `left` is no longer being read from, update its `ReferenceFlags`. - if matches!(ctx.ancestry.parent(), Ancestor::ExpressionStatementExpression(_)) { - *reference.flags_mut() = ReferenceFlags::Write; - } + let pow_left = if let Some(symbol_id) = reference.symbol_id() { + // This variable is declared in scope so evaluating it multiple times can't trigger a getter. + // No need for a temp var. + // `left **= right` is being transformed to `left = Math.pow(left, right)`, + // so if `left` is no longer being read from, update its `ReferenceFlags`. + if matches!(ctx.ancestry.parent(), Ancestor::ExpressionStatementExpression(_)) { + *reference.flags_mut() = ReferenceFlags::Write; + } - Expression::Identifier(ctx.ast.alloc(ctx.create_bound_reference_id( - SPAN, - ident.name.clone(), - symbol_id, - ReferenceFlags::Read, - ))) - } else { - // Unbound reference. Could possibly trigger a getter so we need to only evaluate it once. - // Assign to a temp var. - let reference = Expression::Identifier(ctx.ast.alloc( - ctx.create_unbound_reference_id(SPAN, ident.name.clone(), ReferenceFlags::Read), - )); - let binding = self.create_temp_var(reference, &mut temp_var_inits, ctx); - binding.create_read_expression(ctx) - }; + Expression::Identifier(ctx.ast.alloc(ctx.create_bound_ident_reference( + SPAN, + ident.name.clone(), + symbol_id, + ReferenceFlags::Read, + ))) + } else { + // Unbound reference. Could possibly trigger a getter so we need to only evaluate it once. + // Assign to a temp var. + let reference = Expression::Identifier(ctx.ast.alloc( + ctx.create_unbound_ident_reference(SPAN, ident.name.clone(), ReferenceFlags::Read), + )); + let binding = self.create_temp_var(reference, &mut temp_var_inits, ctx); + binding.create_read_expression(ctx) + }; (pow_left, temp_var_inits) } @@ -496,12 +495,14 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { if let Some(symbol_id) = symbol_id { // This variable is declared in scope so evaluating it multiple times can't trigger a getter. // No need for a temp var. - return Expression::Identifier(ctx.ast.alloc(ctx.create_bound_reference_id( - SPAN, - ident.name.clone(), - symbol_id, - ReferenceFlags::Read, - ))); + return Expression::Identifier(ctx.ast.alloc( + ctx.create_bound_ident_reference( + SPAN, + ident.name.clone(), + symbol_id, + ReferenceFlags::Read, + ), + )); } // Unbound reference. Could possibly trigger a getter so we need to only evaluate it once. // Assign to a temp var. @@ -547,8 +548,12 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let math_symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "Math"); - let ident_math = - ctx.create_reference_id(SPAN, Atom::from("Math"), math_symbol_id, ReferenceFlags::Read); + let ident_math = ctx.create_ident_reference( + SPAN, + Atom::from("Math"), + math_symbol_id, + ReferenceFlags::Read, + ); let object = Expression::Identifier(ctx.alloc(ident_math)); let property = ctx.ast.identifier_name(SPAN, "pow"); let callee = diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index 9ebcb42db1b618..f8fe6520374c19 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -310,7 +310,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { let id = caller_function.id.as_ref().unwrap(); // If the function has an id, then we need to return the id. // `function foo() { ... }` -> `function foo() {} return foo;` - let reference = ctx.create_bound_reference_id( + let reference = ctx.create_bound_ident_reference( SPAN, id.name.clone(), id.symbol_id(), @@ -597,8 +597,12 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "arguments"); - let arguments_ident = - ctx.create_reference_id(SPAN, Atom::from("arguments"), symbol_id, ReferenceFlags::Read); + let arguments_ident = ctx.create_ident_reference( + SPAN, + Atom::from("arguments"), + symbol_id, + ReferenceFlags::Read, + ); let arguments_ident = Argument::Identifier(ctx.alloc(arguments_ident)); // (this, arguments) diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index cb20c5e093abbd..de17587cafea45 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -142,7 +142,7 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { fn object_assign(symbol_id: Option, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { let ident = - ctx.create_reference_id(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read); + ctx.create_ident_reference(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read); let object = Expression::Identifier(ctx.alloc(ident)); let property = ctx.ast.identifier_name(SPAN, Atom::from("assign")); Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index 94697914f44827..e2e8fbf4f491de 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -134,7 +134,7 @@ impl<'a, 'ctx> LogicalAssignmentOperators<'a, 'ctx> { let symbol_id = reference.symbol_id(); let left_expr = Expression::Identifier(ctx.alloc(ident.clone())); - let ident = ctx.create_reference_id( + let ident = ctx.create_ident_reference( SPAN, ident.name.clone(), symbol_id, diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index 4e13e1f60f91e8..adfa56b2065a76 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -336,7 +336,7 @@ impl<'a, 'ctx> Traverse<'a> for ReactRefresh<'a, 'ctx> { binding_name.as_str(), ) .map(|symbol_id| { - let ident = ctx.create_bound_reference_id( + let ident = ctx.create_bound_ident_reference( SPAN, binding_name, symbol_id, @@ -496,7 +496,7 @@ impl<'a, 'ctx> ReactRefresh<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let left = self.create_registration(id.name.clone(), ReferenceFlags::Write, ctx); - let right = ctx.create_bound_reference_id( + let right = ctx.create_bound_ident_reference( SPAN, id.name.clone(), id.symbol_id(), diff --git a/crates/oxc_transformer/src/regexp/mod.rs b/crates/oxc_transformer/src/regexp/mod.rs index a2dfe6c03c2ebd..bf1b816b1946b8 100644 --- a/crates/oxc_transformer/src/regexp/mod.rs +++ b/crates/oxc_transformer/src/regexp/mod.rs @@ -180,7 +180,7 @@ impl<'a, 'ctx> Traverse<'a> for RegExp<'a, 'ctx> { let callee = { let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "RegExp"); - let ident = ctx.create_reference_id( + let ident = ctx.create_ident_reference( SPAN, Atom::from("RegExp"), symbol_id, diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 5866d4b8325f85..708aeacf375b1d 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -122,7 +122,7 @@ impl<'a> TypeScriptEnum<'a> { } else { // }(Foo || {}); let op = LogicalOperator::Or; - let left = ctx.create_bound_reference_id( + let left = ctx.create_bound_ident_reference( decl.id.span, enum_name.clone(), var_symbol_id, @@ -138,7 +138,7 @@ impl<'a> TypeScriptEnum<'a> { if is_already_declared { let op = AssignmentOperator::Assign; - let left = ctx.create_bound_reference_id( + let left = ctx.create_bound_ident_reference( decl.id.span, enum_name.clone(), var_symbol_id, diff --git a/crates/oxc_traverse/src/context/bound_identifier.rs b/crates/oxc_traverse/src/context/bound_identifier.rs index 2761a89c80b09a..5fbaa063b32091 100644 --- a/crates/oxc_traverse/src/context/bound_identifier.rs +++ b/crates/oxc_traverse/src/context/bound_identifier.rs @@ -236,7 +236,7 @@ impl<'a> BoundIdentifier<'a> { flags: ReferenceFlags, ctx: &mut TraverseCtx<'a>, ) -> IdentifierReference<'a> { - ctx.create_bound_reference_id(span, self.name.clone(), self.symbol_id, flags) + ctx.create_bound_ident_reference(span, self.name.clone(), self.symbol_id, flags) } /// Create `Expression::Identifier` referencing this binding, with specified `Span` and `ReferenceFlags` diff --git a/crates/oxc_traverse/src/context/maybe_bound_identifier.rs b/crates/oxc_traverse/src/context/maybe_bound_identifier.rs index 5d7b010f717dff..6dc1451ccf3eda 100644 --- a/crates/oxc_traverse/src/context/maybe_bound_identifier.rs +++ b/crates/oxc_traverse/src/context/maybe_bound_identifier.rs @@ -218,7 +218,7 @@ impl<'a> MaybeBoundIdentifier<'a> { flags: ReferenceFlags, ctx: &mut TraverseCtx<'a>, ) -> IdentifierReference<'a> { - ctx.create_reference_id(span, self.name.clone(), self.symbol_id, flags) + ctx.create_ident_reference(span, self.name.clone(), self.symbol_id, flags) } /// Create `Expression::Identifier` referencing this binding, with specified `Span` and `ReferenceFlags` diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index ac2968dcddfdeb..c9b735bff0ee92 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -434,7 +434,7 @@ impl<'a> TraverseCtx<'a> { } /// Create an `IdentifierReference` bound to a `SymbolId`. - pub fn create_bound_reference_id( + pub fn create_bound_ident_reference( &mut self, span: Span, name: Atom<'a>, @@ -458,7 +458,7 @@ impl<'a> TraverseCtx<'a> { } /// Create an unbound `IdentifierReference`. - pub fn create_unbound_reference_id( + pub fn create_unbound_ident_reference( &mut self, span: Span, name: Atom<'a>, @@ -486,9 +486,9 @@ impl<'a> TraverseCtx<'a> { /// Create an `IdentifierReference` optionally bound to a `SymbolId`. /// - /// If you know if there's a `SymbolId` or not, prefer `TraverseCtx::create_bound_reference_id` - /// or `TraverseCtx::create_unbound_reference_id`. - pub fn create_reference_id( + /// If you know if there's a `SymbolId` or not, prefer `TraverseCtx::create_bound_ident_reference` + /// or `TraverseCtx::create_unbound_ident_reference`. + pub fn create_ident_reference( &mut self, span: Span, name: Atom<'a>, @@ -496,9 +496,9 @@ impl<'a> TraverseCtx<'a> { flags: ReferenceFlags, ) -> IdentifierReference<'a> { if let Some(symbol_id) = symbol_id { - self.create_bound_reference_id(span, name, symbol_id, flags) + self.create_bound_ident_reference(span, name, symbol_id, flags) } else { - self.create_unbound_reference_id(span, name, flags) + self.create_unbound_ident_reference(span, name, flags) } } From ba0b2ff85622bf0485c1bd6993c23ba4cb48e0b0 Mon Sep 17 00:00:00 2001 From: "Alexander S." Date: Sat, 16 Nov 2024 06:34:44 +0100 Subject: [PATCH 005/121] fix(editor): reload workspace configuration after change (#7302) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit after changing `settings.json`, the changes whould not to updated internally. With this PR the updated values get passed to the language-server. πŸ₯³ probably closes https://github.com/oxc-project/backlog/issues/132 because we also support the oxlint config --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- editors/vscode/client/config.ts | 33 +++++++++++++++++---------------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/editors/vscode/client/config.ts b/editors/vscode/client/config.ts index ba553afb13a91d..d2eabe94ec753c 100644 --- a/editors/vscode/client/config.ts +++ b/editors/vscode/client/config.ts @@ -4,11 +4,11 @@ import { IDisposable } from './types'; export class ConfigService implements Config, IDisposable { private static readonly _namespace = 'oxc'; private readonly _disposables: IDisposable[] = []; - private _inner: WorkspaceConfiguration; - private _runTrigger: Trigger; - private _enable: boolean; - private _trace: TraceLevel; - private _configPath: string; + private _inner!: WorkspaceConfiguration; + private _runTrigger!: Trigger; + private _enable!: boolean; + private _trace!: TraceLevel; + private _configPath!: string; private _binPath: string | undefined; public onConfigChange: @@ -16,12 +16,7 @@ export class ConfigService implements Config, IDisposable { | undefined; constructor() { - this._inner = workspace.getConfiguration(ConfigService._namespace); - this._runTrigger = this._inner.get('lint.run') || 'onType'; - this._enable = this._inner.get('enable') ?? true; - this._trace = this._inner.get('trace.server') || 'off'; - this._configPath = this._inner.get('configPath') || '.eslintrc'; - this._binPath = this._inner.get('path.server'); + this.setSettingsFromWorkspace(); this.onConfigChange = undefined; const disposeChangeListener = workspace.onDidChangeConfiguration( @@ -30,6 +25,16 @@ export class ConfigService implements Config, IDisposable { this._disposables.push(disposeChangeListener); } + private setSettingsFromWorkspace(): void { + this._inner = workspace.getConfiguration(ConfigService._namespace); + + this._runTrigger = this._inner.get('lint.run') || 'onType'; + this._enable = this._inner.get('enable') ?? true; + this._trace = this._inner.get('trace.server') || 'off'; + this._configPath = this._inner.get('configPath') || '.eslintrc'; + this._binPath = this._inner.get('path.server'); + } + get runTrigger(): Trigger { return this._runTrigger; } @@ -87,11 +92,7 @@ export class ConfigService implements Config, IDisposable { private onVscodeConfigChange(event: ConfigurationChangeEvent): void { if (event.affectsConfiguration(ConfigService._namespace)) { - this._runTrigger = this._inner.get('lint.run') || 'onType'; - this._enable = this._inner.get('enable') ?? true; - this._trace = this._inner.get('trace.server') || 'off'; - this._configPath = this._inner.get('configPath') || '.eslintrc'; - this._binPath = this._inner.get('path.server'); + this.setSettingsFromWorkspace(); this.onConfigChange?.call(this, event); } } From faf8dde4ffc30a1dce5566d8c7a51f63283b01ca Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sat, 16 Nov 2024 05:36:35 +0000 Subject: [PATCH 006/121] feat(traverse): add methods for creating `Expression::Identifier`s (#7301) It's a common pattern in transformer to call `ctx.create_ident_reference()` and then convert to an `Expression` with `Expression::Identifier(ctx.ast.alloc(ident))`. Add methods to do this in a single method call. --- .../src/common/helper_loader.rs | 9 +--- .../src/common/module_imports.rs | 5 +-- .../src/es2016/exponentiation_operator.rs | 35 +++++----------- .../src/es2017/async_to_generator.rs | 10 ++--- .../src/es2018/object_rest_spread.rs | 5 +-- crates/oxc_transformer/src/jsx/refresh.rs | 6 +-- crates/oxc_transformer/src/regexp/mod.rs | 8 +--- crates/oxc_transformer/src/typescript/enum.rs | 3 +- crates/oxc_traverse/src/context/mod.rs | 41 +++++++++++++++++++ 9 files changed, 66 insertions(+), 56 deletions(-) diff --git a/crates/oxc_transformer/src/common/helper_loader.rs b/crates/oxc_transformer/src/common/helper_loader.rs index 0346c988765ff0..79e42f246dee56 100644 --- a/crates/oxc_transformer/src/common/helper_loader.rs +++ b/crates/oxc_transformer/src/common/helper_loader.rs @@ -277,13 +277,8 @@ impl<'a> HelperLoaderStore<'a> { static HELPER_VAR: &str = "babelHelpers"; let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), HELPER_VAR); - let ident = ctx.create_ident_reference( - SPAN, - Atom::from(HELPER_VAR), - symbol_id, - ReferenceFlags::Read, - ); - let object = Expression::Identifier(ctx.alloc(ident)); + let object = + ctx.create_ident_expr(SPAN, Atom::from(HELPER_VAR), symbol_id, ReferenceFlags::Read); let property = ctx.ast.identifier_name(SPAN, Atom::from(helper.name())); Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) } diff --git a/crates/oxc_transformer/src/common/module_imports.rs b/crates/oxc_transformer/src/common/module_imports.rs index 055849832c546a..94c4c2a1830b21 100644 --- a/crates/oxc_transformer/src/common/module_imports.rs +++ b/crates/oxc_transformer/src/common/module_imports.rs @@ -226,14 +226,12 @@ impl<'a> ModuleImportsStore<'a> { require_symbol_id: Option, ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { - let var_kind = VariableDeclarationKind::Var; - let ident = ctx.create_ident_reference( + let callee = ctx.create_ident_expr( SPAN, Atom::from("require"), require_symbol_id, ReferenceFlags::read(), ); - let callee = Expression::Identifier(ctx.alloc(ident)); let args = { let arg = Argument::from(ctx.ast.expression_string_literal(SPAN, source)); @@ -241,6 +239,7 @@ impl<'a> ModuleImportsStore<'a> { }; let Some(Import::Default(local)) = names.into_iter().next() else { unreachable!() }; let id = local.create_binding_pattern(ctx); + let var_kind = VariableDeclarationKind::Var; let decl = { let init = ctx.ast.expression_call(SPAN, callee, NONE, args, false); let decl = ctx.ast.variable_declarator(SPAN, var_kind, id, Some(init), false); diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 2d787d592135b2..716ade8cf25dd4 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -164,18 +164,12 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { *reference.flags_mut() = ReferenceFlags::Write; } - Expression::Identifier(ctx.ast.alloc(ctx.create_bound_ident_reference( - SPAN, - ident.name.clone(), - symbol_id, - ReferenceFlags::Read, - ))) + ctx.create_bound_ident_expr(SPAN, ident.name.clone(), symbol_id, ReferenceFlags::Read) } else { // Unbound reference. Could possibly trigger a getter so we need to only evaluate it once. // Assign to a temp var. - let reference = Expression::Identifier(ctx.ast.alloc( - ctx.create_unbound_ident_reference(SPAN, ident.name.clone(), ReferenceFlags::Read), - )); + let reference = + ctx.create_unbound_ident_expr(SPAN, ident.name.clone(), ReferenceFlags::Read); let binding = self.create_temp_var(reference, &mut temp_var_inits, ctx); binding.create_read_expression(ctx) }; @@ -495,14 +489,12 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { if let Some(symbol_id) = symbol_id { // This variable is declared in scope so evaluating it multiple times can't trigger a getter. // No need for a temp var. - return Expression::Identifier(ctx.ast.alloc( - ctx.create_bound_ident_reference( - SPAN, - ident.name.clone(), - symbol_id, - ReferenceFlags::Read, - ), - )); + return ctx.create_bound_ident_expr( + SPAN, + ident.name.clone(), + symbol_id, + ReferenceFlags::Read, + ); } // Unbound reference. Could possibly trigger a getter so we need to only evaluate it once. // Assign to a temp var. @@ -548,13 +540,8 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let math_symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "Math"); - let ident_math = ctx.create_ident_reference( - SPAN, - Atom::from("Math"), - math_symbol_id, - ReferenceFlags::Read, - ); - let object = Expression::Identifier(ctx.alloc(ident_math)); + let object = + ctx.create_ident_expr(SPAN, Atom::from("Math"), math_symbol_id, ReferenceFlags::Read); let property = ctx.ast.identifier_name(SPAN, "pow"); let callee = Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)); diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index f8fe6520374c19..97cfab30326d73 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -310,7 +310,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { let id = caller_function.id.as_ref().unwrap(); // If the function has an id, then we need to return the id. // `function foo() { ... }` -> `function foo() {} return foo;` - let reference = ctx.create_bound_ident_reference( + let reference = ctx.create_bound_ident_expr( SPAN, id.name.clone(), id.symbol_id(), @@ -318,8 +318,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { ); let statement = Statement::FunctionDeclaration(caller_function); statements.push(statement); - let argument = Some(Expression::Identifier(ctx.alloc(reference))); - statements.push(ctx.ast.statement_return(SPAN, argument)); + statements.push(ctx.ast.statement_return(SPAN, Some(reference))); } else { // If the function doesn't have an id, then we need to return the function itself. // `function() { ... }` -> `return function() { ... };` @@ -597,13 +596,12 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "arguments"); - let arguments_ident = ctx.create_ident_reference( + let arguments_ident = Argument::from(ctx.create_ident_expr( SPAN, Atom::from("arguments"), symbol_id, ReferenceFlags::Read, - ); - let arguments_ident = Argument::Identifier(ctx.alloc(arguments_ident)); + )); // (this, arguments) let mut arguments = ctx.ast.vec_with_capacity(2); diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index de17587cafea45..0daaf88ca3aa2c 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -141,9 +141,8 @@ impl<'a, 'ctx> ObjectRestSpread<'a, 'ctx> { } fn object_assign(symbol_id: Option, ctx: &mut TraverseCtx<'a>) -> Expression<'a> { - let ident = - ctx.create_ident_reference(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read); - let object = Expression::Identifier(ctx.alloc(ident)); + let object = + ctx.create_ident_expr(SPAN, Atom::from("Object"), symbol_id, ReferenceFlags::Read); let property = ctx.ast.identifier_name(SPAN, Atom::from("assign")); Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)) } diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index adfa56b2065a76..0598d5150719e5 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -336,13 +336,12 @@ impl<'a, 'ctx> Traverse<'a> for ReactRefresh<'a, 'ctx> { binding_name.as_str(), ) .map(|symbol_id| { - let ident = ctx.create_bound_ident_reference( + let mut expr = ctx.create_bound_ident_expr( SPAN, binding_name, symbol_id, ReferenceFlags::Read, ); - let mut expr = Expression::Identifier(ctx.alloc(ident)); if is_member_expression { // binding_name.hook_name @@ -496,13 +495,12 @@ impl<'a, 'ctx> ReactRefresh<'a, 'ctx> { ctx: &mut TraverseCtx<'a>, ) -> Statement<'a> { let left = self.create_registration(id.name.clone(), ReferenceFlags::Write, ctx); - let right = ctx.create_bound_ident_reference( + let right = ctx.create_bound_ident_expr( SPAN, id.name.clone(), id.symbol_id(), ReferenceFlags::Read, ); - let right = Expression::Identifier(ctx.alloc(right)); let expr = ctx.ast.expression_assignment(SPAN, AssignmentOperator::Assign, left, right); ctx.ast.statement_expression(SPAN, expr) } diff --git a/crates/oxc_transformer/src/regexp/mod.rs b/crates/oxc_transformer/src/regexp/mod.rs index bf1b816b1946b8..fdb69fdb00746c 100644 --- a/crates/oxc_transformer/src/regexp/mod.rs +++ b/crates/oxc_transformer/src/regexp/mod.rs @@ -180,13 +180,7 @@ impl<'a, 'ctx> Traverse<'a> for RegExp<'a, 'ctx> { let callee = { let symbol_id = ctx.scopes().find_binding(ctx.current_scope_id(), "RegExp"); - let ident = ctx.create_ident_reference( - SPAN, - Atom::from("RegExp"), - symbol_id, - ReferenceFlags::read(), - ); - Expression::Identifier(ctx.alloc(ident)) + ctx.create_ident_expr(SPAN, Atom::from("RegExp"), symbol_id, ReferenceFlags::read()) }; let mut arguments = ctx.ast.vec_with_capacity(2); diff --git a/crates/oxc_transformer/src/typescript/enum.rs b/crates/oxc_transformer/src/typescript/enum.rs index 708aeacf375b1d..b503f9ff327040 100644 --- a/crates/oxc_transformer/src/typescript/enum.rs +++ b/crates/oxc_transformer/src/typescript/enum.rs @@ -122,13 +122,12 @@ impl<'a> TypeScriptEnum<'a> { } else { // }(Foo || {}); let op = LogicalOperator::Or; - let left = ctx.create_bound_ident_reference( + let left = ctx.create_bound_ident_expr( decl.id.span, enum_name.clone(), var_symbol_id, ReferenceFlags::Read, ); - let left = Expression::Identifier(ctx.alloc(left)); let right = ast.expression_object(SPAN, ast.vec(), None); let expression = ast.expression_logical(SPAN, left, op, right); ast.vec1(Argument::from(expression)) diff --git a/crates/oxc_traverse/src/context/mod.rs b/crates/oxc_traverse/src/context/mod.rs index c9b735bff0ee92..eda09ba266cc6c 100644 --- a/crates/oxc_traverse/src/context/mod.rs +++ b/crates/oxc_traverse/src/context/mod.rs @@ -445,6 +445,18 @@ impl<'a> TraverseCtx<'a> { self.ast.identifier_reference_with_reference_id(span, name, reference_id) } + /// Create an `Expression::Identifier` bound to a `SymbolId`. + pub fn create_bound_ident_expr( + &mut self, + span: Span, + name: Atom<'a>, + symbol_id: SymbolId, + flags: ReferenceFlags, + ) -> Expression<'a> { + let ident = self.create_bound_ident_reference(span, name, symbol_id, flags); + Expression::Identifier(self.ast.alloc(ident)) + } + /// Create an unbound reference. /// /// This is a shortcut for `ctx.scoping.create_unbound_reference`. @@ -468,6 +480,17 @@ impl<'a> TraverseCtx<'a> { self.ast.identifier_reference_with_reference_id(span, name, reference_id) } + /// Create an unbound `Expression::Identifier`. + pub fn create_unbound_ident_expr( + &mut self, + span: Span, + name: Atom<'a>, + flags: ReferenceFlags, + ) -> Expression<'a> { + let ident = self.create_unbound_ident_reference(span, name, flags); + Expression::Identifier(self.ast.alloc(ident)) + } + /// Create a reference optionally bound to a `SymbolId`. /// /// If you know if there's a `SymbolId` or not, prefer `TraverseCtx::create_bound_reference` @@ -502,6 +525,24 @@ impl<'a> TraverseCtx<'a> { } } + /// Create an `Expression::Identifier` optionally bound to a `SymbolId`. + /// + /// If you know if there's a `SymbolId` or not, prefer `TraverseCtx::create_bound_ident_expr` + /// or `TraverseCtx::create_unbound_ident_expr`. + pub fn create_ident_expr( + &mut self, + span: Span, + name: Atom<'a>, + symbol_id: Option, + flags: ReferenceFlags, + ) -> Expression<'a> { + if let Some(symbol_id) = symbol_id { + self.create_bound_ident_expr(span, name, symbol_id, flags) + } else { + self.create_unbound_ident_expr(span, name, flags) + } + } + /// Create reference in current scope, looking up binding for `name`, /// /// This is a shortcut for `ctx.scoping.create_reference_in_current_scope`. From 4acf2db82bef84177bf39de37f417d487e6b3518 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sat, 16 Nov 2024 05:36:35 +0000 Subject: [PATCH 007/121] refactor(transformer): helper loader methods take `Span` (#7304) `TransformCtx::helper_call` and `TransformCtx::helper_call_expr` take a `Span`. Sometimes the helper call replaces some original code, and should have the same span as the original code. --- crates/oxc_transformer/src/common/helper_loader.rs | 8 +++++--- crates/oxc_transformer/src/es2017/async_to_generator.rs | 2 +- .../src/es2018/async_generator_functions/for_await.rs | 1 + .../src/es2018/async_generator_functions/mod.rs | 8 +++++--- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/crates/oxc_transformer/src/common/helper_loader.rs b/crates/oxc_transformer/src/common/helper_loader.rs index 79e42f246dee56..10e3a3c62452ce 100644 --- a/crates/oxc_transformer/src/common/helper_loader.rs +++ b/crates/oxc_transformer/src/common/helper_loader.rs @@ -73,7 +73,7 @@ use serde::Deserialize; use oxc_allocator::{String as ArenaString, Vec as ArenaVec}; use oxc_ast::ast::{Argument, CallExpression, Expression, TSTypeParameterInstantiation}; use oxc_semantic::{ReferenceFlags, SymbolFlags}; -use oxc_span::{Atom, SPAN}; +use oxc_span::{Atom, Span, SPAN}; use oxc_traverse::{BoundIdentifier, TraverseCtx}; use crate::TransformCtx; @@ -183,12 +183,13 @@ impl<'a> TransformCtx<'a> { pub fn helper_call( &self, helper: Helper, + span: Span, arguments: ArenaVec<'a, Argument<'a>>, ctx: &mut TraverseCtx<'a>, ) -> CallExpression<'a> { let callee = self.helper_load(helper, ctx); ctx.ast.call_expression( - SPAN, + span, callee, None::>, arguments, @@ -200,12 +201,13 @@ impl<'a> TransformCtx<'a> { pub fn helper_call_expr( &self, helper: Helper, + span: Span, arguments: ArenaVec<'a, Argument<'a>>, ctx: &mut TraverseCtx<'a>, ) -> Expression<'a> { let callee = self.helper_load(helper, ctx); ctx.ast.expression_call( - SPAN, + span, callee, None::>, arguments, diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index 97cfab30326d73..c7107ee576cc75 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -639,7 +639,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { let mut function = Self::create_function(None, params, body, scope_id, ctx); function.generator = true; let arguments = ctx.ast.vec1(Argument::FunctionExpression(function)); - self.ctx.helper_call_expr(self.helper, arguments, ctx) + self.ctx.helper_call_expr(self.helper, SPAN, arguments, ctx) } /// Creates a helper declaration statement for async-to-generator transformation. diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs index b83767d63afd29..7e006971401610 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs @@ -150,6 +150,7 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { let iterator = ctx.ast.move_expression(&mut stmt.right); let iterator = self.ctx.helper_call_expr( Helper::AsyncIterator, + SPAN, ctx.ast.vec1(Argument::from(iterator)), ctx, ); diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs index 0ca70e15210a10..1b0d5c93291158 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs @@ -166,9 +166,11 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { expr.argument.as_mut().map(|argument| { let argument = Argument::from(ctx.ast.move_expression(argument)); let arguments = ctx.ast.vec1(argument); - let mut argument = self.ctx.helper_call_expr(Helper::AsyncIterator, arguments, ctx); + let mut argument = + self.ctx.helper_call_expr(Helper::AsyncIterator, SPAN, arguments, ctx); let arguments = ctx.ast.vec1(Argument::from(argument)); - argument = self.ctx.helper_call_expr(Helper::AsyncGeneratorDelegate, arguments, ctx); + argument = + self.ctx.helper_call_expr(Helper::AsyncGeneratorDelegate, SPAN, arguments, ctx); ctx.ast.expression_yield(SPAN, expr.delegate, Some(argument)) }) } @@ -199,7 +201,7 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { let mut argument = ctx.ast.move_expression(&mut expr.argument); let arguments = ctx.ast.vec1(Argument::from(argument)); - argument = self.ctx.helper_call_expr(Helper::AwaitAsyncGenerator, arguments, ctx); + argument = self.ctx.helper_call_expr(Helper::AwaitAsyncGenerator, SPAN, arguments, ctx); Some(ctx.ast.expression_yield(SPAN, false, Some(argument))) } From d135d3ec48b3166abb6d1bac83bab9196ce0e59e Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sat, 16 Nov 2024 05:36:36 +0000 Subject: [PATCH 008/121] feat(data_structures): add methods to `SparseStack` (#7305) Add methods to `SparseStack` to get the filled entries as a slice, and get their length. --- crates/oxc_data_structures/src/stack/sparse.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/crates/oxc_data_structures/src/stack/sparse.rs b/crates/oxc_data_structures/src/stack/sparse.rs index 847d05c62f3522..9880fb4f1ca1fd 100644 --- a/crates/oxc_data_structures/src/stack/sparse.rs +++ b/crates/oxc_data_structures/src/stack/sparse.rs @@ -192,6 +192,12 @@ impl SparseStack { self.has_values.len() } + /// Get number of filled entries on the stack. + #[inline] + pub fn filled_len(&self) -> usize { + self.values.len() + } + /// Get capacity of stack for any entries (either `Some` or `None`). /// /// Capacity is always at least 1. Stack is never empty. @@ -209,4 +215,16 @@ impl SparseStack { pub fn filled_capacity(&self) -> usize { self.values.capacity() } + + /// Get filled entries of stack as a slice `&[T]`. + #[inline] + pub fn as_slice(&self) -> &[T] { + self.values.as_slice() + } + + /// Get filled entries of stack as a mutable slice `&mut [T]`. + #[inline] + pub fn as_mut_slice(&mut self) -> &mut [T] { + self.values.as_mut_slice() + } } From 20d9080d59594f2ab202e7d9a8708ef4a4c0d2e8 Mon Sep 17 00:00:00 2001 From: camchenry <1514176+camchenry@users.noreply.github.com> Date: Sat, 16 Nov 2024 05:54:05 +0000 Subject: [PATCH 009/121] fix(linter)!: override plugins array when passed in config file (#7303) - fixes https://github.com/oxc-project/oxc/issues/6896 When the `plugins` config property is specified, it will overwrite the default plugins array. This allows the plugins list to be easily customized and allows for disabling default plugins at the same time as enabling non-default ones. - example: `{ "plugins": [] }` will enable no plugins. - example: `{ }` will enable default plugins. - example: `{ "plugins": ["typescript", "import"] }` will enable only the import and typescript plugins. --- crates/oxc_linter/src/config/oxlintrc.rs | 35 ++++++++++++------------ crates/oxc_linter/src/config/plugins.rs | 2 +- 2 files changed, 18 insertions(+), 19 deletions(-) diff --git a/crates/oxc_linter/src/config/oxlintrc.rs b/crates/oxc_linter/src/config/oxlintrc.rs index a621eddf25af03..fc96ea1b2d41b6 100644 --- a/crates/oxc_linter/src/config/oxlintrc.rs +++ b/crates/oxc_linter/src/config/oxlintrc.rs @@ -142,29 +142,28 @@ mod test { #[test] fn test_oxlintrc_de_plugins_empty_array() { let config: Oxlintrc = serde_json::from_value(json!({ "plugins": [] })).unwrap(); - assert_eq!(config.plugins, LintPlugins::default()); + assert_eq!(config.plugins, LintPlugins::empty()); } #[test] - fn test_oxlintrc_de_plugins_enabled_by_default() { - // NOTE(@DonIsaac): creating a Value with `json!` then deserializing it with serde_json::from_value - // Errs with "invalid type: string \"eslint\", expected a borrowed string" and I can't - // figure out why. This seems to work. Why??? - let configs = [ - r#"{ "plugins": ["eslint"] }"#, - r#"{ "plugins": ["oxc"] }"#, - r#"{ "plugins": ["deepscan"] }"#, // alias for oxc - ]; - // ^ these plugins are enabled by default already - for oxlintrc in configs { - let config: Oxlintrc = serde_json::from_str(oxlintrc).unwrap(); - assert_eq!(config.plugins, LintPlugins::default()); - } + fn test_oxlintrc_empty_config_plugins() { + let config: Oxlintrc = serde_json::from_str(r"{}").unwrap(); + assert_eq!(config.plugins, LintPlugins::default()); } #[test] - fn test_oxlintrc_de_plugins_new() { - let config: Oxlintrc = serde_json::from_str(r#"{ "plugins": ["import"] }"#).unwrap(); - assert_eq!(config.plugins, LintPlugins::default().union(LintPlugins::IMPORT)); + fn test_oxlintrc_specifying_plugins_will_override() { + let config: Oxlintrc = serde_json::from_str(r#"{ "plugins": ["react", "oxc"] }"#).unwrap(); + assert_eq!(config.plugins, LintPlugins::REACT.union(LintPlugins::OXC)); + let config: Oxlintrc = + serde_json::from_str(r#"{ "plugins": ["typescript", "unicorn"] }"#).unwrap(); + assert_eq!(config.plugins, LintPlugins::TYPESCRIPT.union(LintPlugins::UNICORN)); + let config: Oxlintrc = + serde_json::from_str(r#"{ "plugins": ["typescript", "unicorn", "react", "oxc", "import", "jsdoc", "jest", "vitest", "jsx-a11y", "nextjs", "react-perf", "promise", "node", "security"] }"#).unwrap(); + assert_eq!(config.plugins, LintPlugins::all()); + + let config: Oxlintrc = + serde_json::from_str(r#"{ "plugins": ["typescript", "@typescript-eslint"] }"#).unwrap(); + assert_eq!(config.plugins, LintPlugins::TYPESCRIPT); } } diff --git a/crates/oxc_linter/src/config/plugins.rs b/crates/oxc_linter/src/config/plugins.rs index 9099a1e55da32f..b507b32a351d22 100644 --- a/crates/oxc_linter/src/config/plugins.rs +++ b/crates/oxc_linter/src/config/plugins.rs @@ -178,7 +178,7 @@ impl<'de> Deserialize<'de> for LintPlugins { where A: de::SeqAccess<'de>, { - let mut plugins = LintPlugins::default(); + let mut plugins = LintPlugins::empty(); loop { // serde_json::from_str will provide an &str, while // serde_json::from_value provides a String. The former is From cf99be0a0d873f0c111cae9c84ef9198bcc7feca Mon Sep 17 00:00:00 2001 From: 7086cmd <54303040+7086cmd@users.noreply.github.com> Date: Sat, 16 Nov 2024 06:01:05 +0000 Subject: [PATCH 010/121] fix(minifier): do not compare bigint with object (#7294) @Boshen, could you please update the snap of runtime and commit to this PR? I want to see the effects after the unit tests are added. --- .../src/ast_passes/peephole_fold_constants.rs | 11 +++++++++-- .../peephole_substitute_alternate_syntax.rs | 2 +- tasks/coverage/snapshots/runtime.snap | 8 +------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index 4684b17df673fa..d7397ff5c24358 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -362,14 +362,14 @@ impl<'a, 'b> PeepholeFoldConstants { } } - if matches!(left, ValueType::String | ValueType::Number) + if matches!(left, ValueType::String | ValueType::Number | ValueType::BigInt) && matches!(right, ValueType::Object) { return None; } if matches!(left, ValueType::Object) - && matches!(right, ValueType::String | ValueType::Number) + && matches!(right, ValueType::String | ValueType::Number | ValueType::BigInt) { return None; } @@ -873,6 +873,13 @@ mod test { test("'1' !== 1n", "true"); } + #[test] + fn test_object_bigint_comparison() { + test_same("{ valueOf: function() { return 0n; } } != 0n"); + test_same("0n != { valueOf: function() { return 0n; } }"); + test_same("0n != { toString: function() { return '0'; } }"); + } + #[test] fn test_nan_comparison() { test("NaN < 1", "false"); diff --git a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs index a9063cad0d13d3..381db25a375e0f 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs @@ -18,7 +18,7 @@ use crate::{node_util::Ctx, CompressorPass}; pub struct PeepholeSubstituteAlternateSyntax { /// Do not compress syntaxes that are hard to analyze inside the fixed loop. /// e.g. Do not compress `undefined -> void 0`, `true` -> `!0`. - /// Opposite of `late` in Closure Compier. + /// Opposite of `late` in Closure Compiler. in_fixed_loop: bool, // states diff --git a/tasks/coverage/snapshots/runtime.snap b/tasks/coverage/snapshots/runtime.snap index 51f7b2b1b3491c..fdf09af2d9d362 100644 --- a/tasks/coverage/snapshots/runtime.snap +++ b/tasks/coverage/snapshots/runtime.snap @@ -2,7 +2,7 @@ commit: 06454619 runtime Summary: AST Parsed : 18055/18055 (100.00%) -Positive Passed: 17796/18055 (98.57%) +Positive Passed: 17798/18055 (98.58%) tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-multiple.js transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true @@ -447,12 +447,6 @@ transform error: Test262Error: Expected a TypeError to be thrown but no exceptio tasks/coverage/test262/test/language/expressions/class/heritage-async-arrow-function.js transform error: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all -tasks/coverage/test262/test/language/expressions/does-not-equals/bigint-and-object.js -minify error: Test262Error: The result of (0n != {valueOf: function() {return 0n;}}) is false Expected SameValue(Β«trueΒ», Β«falseΒ») to be true - -tasks/coverage/test262/test/language/expressions/equals/bigint-and-object.js -minify error: Test262Error: The result of (0n == {valueOf: function() {return 0n;}}) is true Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/exponentiation/bigint-negative-exponent-throws.js transform error: Test262Error: (-1n) ** -1n throws RangeError Expected a RangeError but got a TypeError From 4c124a86eae5a14a7258b46a76b72cb367d9781f Mon Sep 17 00:00:00 2001 From: Nicholas Rayburn <52075362+nrayburn-tech@users.noreply.github.com> Date: Sat, 16 Nov 2024 00:53:51 -0600 Subject: [PATCH 011/121] docs(editor/vscode): Update VS Code readme with installation instructions and available features (#7306) --- editors/vscode/README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/editors/vscode/README.md b/editors/vscode/README.md index c4298105aff819..8bee6d1f994eee 100644 --- a/editors/vscode/README.md +++ b/editors/vscode/README.md @@ -2,6 +2,17 @@ The Oxidation Compiler is creating a suite of high-performance tools for JavaScript and TypeScript. +## Installation + +Any of the below options can be used to install the extension. + +- Install through the VS Code extensions marketplace by searching for `Oxc`. Verify the identifier is `oxc.oxc-vscode`. +- From within VS Code, open the Quick Open (Ctrl+P or Cmd+P on macOS) and execute `ext install oxc.oxc-vscode`. + ## Oxlint -This is the linter for oxc. +This is the linter for Oxc. The currently supported features are listed below. + +- Highlighting for warnings or errors identified by Oxlint +- Quick fixes to fix a warning or error when possible +- JSON schema validation for supported Oxlint configuration files (does not include ESLint configuration files) From cf3415b0e4a77b146ca4adc36b5c00c714a8062a Mon Sep 17 00:00:00 2001 From: Song Gao <158983297@qq.com> Date: Sat, 16 Nov 2024 21:00:30 +0800 Subject: [PATCH 012/121] chore(doc): replace main/master to tag/commit to make the url always accessible (#7298) --- crates/oxc/src/napi/parse.rs | 2 +- crates/oxc/src/napi/transform.rs | 4 ++-- crates/oxc_allocator/src/boxed.rs | 2 +- crates/oxc_allocator/src/vec.rs | 2 +- crates/oxc_ast/src/ast/js.rs | 2 +- crates/oxc_ast/src/ast/ts.rs | 2 +- crates/oxc_ast/src/ast_impl/ts.rs | 2 +- crates/oxc_ast/src/generated/visit.rs | 2 +- crates/oxc_ast/src/generated/visit_mut.rs | 2 +- crates/oxc_ast/src/lib.rs | 2 +- crates/oxc_codegen/src/comment.rs | 2 +- crates/oxc_codegen/src/gen.rs | 2 +- crates/oxc_codegen/src/lib.rs | 2 +- .../oxc_codegen/tests/integration/esbuild.rs | 4 ++-- .../tests/integration/pure_comments.rs | 2 +- crates/oxc_codegen/tests/integration/unit.rs | 2 +- crates/oxc_diagnostics/src/reporter/json.rs | 2 +- crates/oxc_diagnostics/src/reporter/unix.rs | 2 +- crates/oxc_isolated_declarations/src/lib.rs | 2 +- .../tests/deno/mod.rs | 2 +- .../oxc_linter/src/config/settings/jsdoc.rs | 4 ++-- crates/oxc_linter/src/fixer/fix.rs | 4 ++-- crates/oxc_linter/src/fixer/mod.rs | 4 ++-- crates/oxc_linter/src/globals.rs | 4 ++-- .../rules/eslint/array_callback_return/mod.rs | 2 +- .../src/rules/eslint/no_control_regex.rs | 2 +- .../rules/eslint/no_empty_character_class.rs | 2 +- crates/oxc_linter/src/rules/eslint/no_eval.rs | 2 +- .../src/rules/eslint/no_obj_calls.rs | 2 +- .../src/rules/eslint/no_useless_escape.rs | 4 ++-- crates/oxc_linter/src/rules/eslint/no_var.rs | 6 ++--- crates/oxc_linter/src/rules/eslint/radix.rs | 6 ++--- crates/oxc_linter/src/rules/import/default.rs | 2 +- crates/oxc_linter/src/rules/import/export.rs | 2 +- crates/oxc_linter/src/rules/import/first.rs | 2 +- .../src/rules/import/import_no_namespace.rs | 2 +- .../src/rules/import/max_dependencies.rs | 2 +- crates/oxc_linter/src/rules/import/named.rs | 2 +- .../oxc_linter/src/rules/import/namespace.rs | 2 +- crates/oxc_linter/src/rules/import/no_amd.rs | 2 +- .../src/rules/import/no_commonjs.rs | 2 +- .../oxc_linter/src/rules/import/no_cycle.rs | 2 +- .../src/rules/import/no_deprecated.rs | 2 +- .../src/rules/import/no_duplicates.rs | 2 +- .../src/rules/import/no_named_as_default.rs | 2 +- .../import/no_named_as_default_member.rs | 2 +- .../src/rules/import/no_unused_modules.rs | 2 +- .../src/rules/import/unambiguous.rs | 2 +- .../src/rules/jest/consistent_test_it.rs | 2 +- .../src/rules/jest/expect_expect.rs | 2 +- .../src/rules/jest/no_alias_methods.rs | 2 +- .../src/rules/jest/no_commented_out_tests.rs | 2 +- .../src/rules/jest/no_conditional_expect.rs | 2 +- .../src/rules/jest/no_disabled_tests.rs | 2 +- .../src/rules/jest/no_focused_tests.rs | 2 +- .../src/rules/jest/no_identical_title.rs | 2 +- .../src/rules/jest/no_jasmine_globals.rs | 2 +- .../src/rules/jest/no_mocks_import.rs | 2 +- .../src/rules/jest/no_standalone_expect.rs | 2 +- .../src/rules/jest/no_test_prefixes.rs | 2 +- .../src/rules/jest/prefer_hooks_in_order.rs | 2 +- .../src/rules/jest/valid_describe_callback.rs | 2 +- .../oxc_linter/src/rules/jest/valid_expect.rs | 2 +- crates/oxc_linter/src/rules/jsx_a11y/lang.rs | 2 +- .../jsx_a11y/role_supports_aria_props.rs | 2 +- .../rules/nextjs/no_unwanted_polyfillio.rs | 2 +- .../src/rules/oxc/no_accumulating_spread.rs | 4 ++-- .../rules/react/no_direct_mutation_state.rs | 6 ++--- .../src/rules/security/api_keys/mod.rs | 2 +- .../no_side_effects_in_initialization/mod.rs | 2 +- .../typescript/consistent_type_imports.rs | 2 +- crates/oxc_linter/src/utils/react.rs | 6 ++--- crates/oxc_linter/src/utils/unicorn.rs | 2 +- crates/oxc_mangler/src/lib.rs | 2 +- crates/oxc_minifier/README.md | 2 +- .../collapse_variable_declarations.rs | 4 ++-- .../src/ast_passes/exploit_assigns.rs | 4 ++-- .../src/ast_passes/peephole_fold_constants.rs | 6 ++--- .../peephole_minimize_conditions.rs | 4 ++-- .../ast_passes/peephole_remove_dead_code.rs | 4 ++-- .../peephole_replace_known_methods.rs | 4 ++-- .../peephole_substitute_alternate_syntax.rs | 4 ++-- .../src/ast_passes/statement_fusion.rs | 2 +- .../tests/ast_passes/dead_code_elimination.rs | 2 +- .../oxc_module_lexer/tests/integration/esm.rs | 2 +- crates/oxc_parser/src/js/statement.rs | 2 +- crates/oxc_parser/src/lexer/byte_handlers.rs | 2 +- crates/oxc_parser/src/lexer/mod.rs | 6 ++--- crates/oxc_parser/src/lexer/number.rs | 2 +- crates/oxc_prettier/README.md | 2 +- crates/oxc_prettier/src/doc.rs | 4 ++-- .../oxc_prettier/src/format/call_arguments.rs | 2 +- crates/oxc_prettier/src/format/mod.rs | 4 ++-- crates/oxc_prettier/src/lib.rs | 2 +- crates/oxc_prettier/src/needs_parens.rs | 2 +- crates/oxc_prettier/src/options.rs | 4 ++-- crates/oxc_prettier/src/printer/mod.rs | 4 ++-- crates/oxc_sourcemap/src/decode.rs | 4 ++-- crates/oxc_sourcemap/src/encode.rs | 2 +- .../src/common/helper_loader.rs | 6 ++--- .../src/common/module_imports.rs | 2 +- .../src/es2015/arrow_functions.rs | 2 +- .../src/es2016/exponentiation_operator.rs | 4 ++-- .../src/es2017/async_to_generator.rs | 2 +- .../es2018/async_generator_functions/mod.rs | 2 +- .../src/es2018/object_rest_spread.rs | 2 +- .../src/es2019/optional_catch_binding.rs | 2 +- .../src/es2020/nullish_coalescing_operator.rs | 2 +- .../es2021/logical_assignment_operators.rs | 2 +- .../src/es2022/class_properties.rs | 6 ++--- .../src/es2022/class_static_block.rs | 2 +- .../oxc_transformer/src/jsx/display_name.rs | 2 +- crates/oxc_transformer/src/jsx/jsx_impl.rs | 2 +- crates/oxc_transformer/src/jsx/jsx_self.rs | 2 +- crates/oxc_transformer/src/jsx/jsx_source.rs | 2 +- crates/oxc_transformer/src/jsx/refresh.rs | 2 +- crates/oxc_transformer/src/lib.rs | 2 +- .../plugins/inject_global_variables.rs | 2 +- napi/parser/index.d.ts | 2 +- napi/transform/index.d.ts | 2 +- npm/oxc-parser/scripts/generate-packages.mjs | 2 +- .../scripts/generate-packages.mjs | 2 +- npm/oxlint/scripts/generate-packages.mjs | 2 +- tasks/ast_tools/src/generators/visit.rs | 2 +- tasks/common/src/test_file.rs | 2 +- tasks/compat_data/README.md | 2 +- tasks/compat_data/build.js | 4 ++-- tasks/compat_data/chromium-to-electron.js | 2 +- tasks/compat_data/chromium-versions.js | 2 +- tasks/compat_data/es-features.js | 4 ++-- tasks/coverage/misc/fail/oxc-2394.ts | 2 +- tasks/coverage/src/runtime/runtime.js | 2 +- tasks/coverage/src/suite.rs | 2 +- tasks/coverage/src/test262/mod.rs | 2 +- .../src/typescript/transpile_runner.rs | 2 +- tasks/lint_rules/src/eslint-rules.cjs | 24 +++++++++---------- .../fixtures/refresh/react-refresh/README.md | 2 +- 137 files changed, 186 insertions(+), 186 deletions(-) diff --git a/crates/oxc/src/napi/parse.rs b/crates/oxc/src/napi/parse.rs index 6ab5d3ce8e3df8..2406a04b417f0f 100644 --- a/crates/oxc/src/napi/parse.rs +++ b/crates/oxc/src/napi/parse.rs @@ -2,7 +2,7 @@ use napi_derive::napi; /// Babel Parser Options /// -/// +/// #[napi(object)] #[derive(Default)] pub struct ParserOptions { diff --git a/crates/oxc/src/napi/transform.rs b/crates/oxc/src/napi/transform.rs index a4f29d2f985ded..d37ae5db6588ac 100644 --- a/crates/oxc/src/napi/transform.rs +++ b/crates/oxc/src/napi/transform.rs @@ -1,4 +1,4 @@ -// NOTE: Types must be aligned with [@types/babel__core](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/babel__core/index.d.ts). +// NOTE: Types must be aligned with [@types/babel__core](https://github.com/DefinitelyTyped/DefinitelyTyped/blob/b5dc32740d9b45d11cff9b025896dd333c795b39/types/babel__core/index.d.ts). #![allow(rustdoc::bare_urls)] @@ -241,7 +241,7 @@ pub struct JsxOptions { /// Enable React Fast Refresh . /// - /// Conforms to the implementation in {@link https://github.com/facebook/react/tree/main/packages/react-refresh} + /// Conforms to the implementation in {@link https://github.com/facebook/react/tree/v18.3.1/packages/react-refresh} /// /// @default false pub refresh: Option>, diff --git a/crates/oxc_allocator/src/boxed.rs b/crates/oxc_allocator/src/boxed.rs index 209e6011d76126..3271631cb1c121 100644 --- a/crates/oxc_allocator/src/boxed.rs +++ b/crates/oxc_allocator/src/boxed.rs @@ -1,6 +1,6 @@ //! Arena Box. //! -//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/ast/src/arena.rs) +//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/ast/src/arena.rs) use std::{ self, diff --git a/crates/oxc_allocator/src/vec.rs b/crates/oxc_allocator/src/vec.rs index 273120f69e66cc..471e47e47fc1c3 100644 --- a/crates/oxc_allocator/src/vec.rs +++ b/crates/oxc_allocator/src/vec.rs @@ -1,6 +1,6 @@ //! Arena Vec. //! -//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/ast/src/arena.rs) +//! Originally based on [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/ast/src/arena.rs) use std::{ self, diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 06107e41dd75eb..4d6d7bf766f8ee 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -2414,7 +2414,7 @@ pub enum ExportDefaultDeclarationKind<'a> { /// Supports: /// * `import {"\0 any unicode" as foo} from ""` /// * `export {foo as "\0 any unicode"}` -/// * es2022: +/// * es2022: /// * #[ast(visit)] #[derive(Debug, Clone)] diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index e96b3ad41996a4..81033cd8a49878 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -1,6 +1,6 @@ //! TypeScript Definitions //! -//! - [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/ast-spec) +//! - [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/v8.9.0/packages/ast-spec) //! - [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md) #![allow(missing_docs)] // FIXME diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 4eff1693778d44..019a5d32cfa05b 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -1,6 +1,6 @@ //! TypeScript Definitions //! -//! [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/ast-spec) +//! [AST Spec](https://github.com/typescript-eslint/typescript-eslint/tree/v8.9.0/packages/ast-spec) //! [Archived TypeScript spec](https://github.com/microsoft/TypeScript/blob/3c99d50da5a579d9fa92d02664b1b66d4ff55944/doc/spec-ARCHIVED.md) #![warn(missing_docs)] diff --git a/crates/oxc_ast/src/generated/visit.rs b/crates/oxc_ast/src/generated/visit.rs index 06d8fbcf2d0c64..a528d712d37378 100644 --- a/crates/oxc_ast/src/generated/visit.rs +++ b/crates/oxc_ast/src/generated/visit.rs @@ -5,7 +5,7 @@ //! //! See: //! * [visitor pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/visitor.html) -//! * [rustc visitor](https://github.com/rust-lang/rust/blob/master/compiler/rustc_ast/src/visit.rs) +//! * [rustc visitor](https://github.com/rust-lang/rust/blob/1.82.0/compiler/rustc_ast/src/visit.rs) #![allow( unused_variables, diff --git a/crates/oxc_ast/src/generated/visit_mut.rs b/crates/oxc_ast/src/generated/visit_mut.rs index f0072a152aecb4..47d62f6254762a 100644 --- a/crates/oxc_ast/src/generated/visit_mut.rs +++ b/crates/oxc_ast/src/generated/visit_mut.rs @@ -5,7 +5,7 @@ //! //! See: //! * [visitor pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/visitor.html) -//! * [rustc visitor](https://github.com/rust-lang/rust/blob/master/compiler/rustc_ast/src/visit.rs) +//! * [rustc visitor](https://github.com/rust-lang/rust/blob/1.82.0/compiler/rustc_ast/src/visit.rs) #![allow( unused_variables, diff --git a/crates/oxc_ast/src/lib.rs b/crates/oxc_ast/src/lib.rs index 4968f7a40a3839..55532ec05f99f6 100644 --- a/crates/oxc_ast/src/lib.rs +++ b/crates/oxc_ast/src/lib.rs @@ -34,7 +34,7 @@ //! [`oxc_parser`]: //! [`Parser`]: //! [estree]: -//! [typescript-eslint]: +//! [typescript-eslint]: //! [ECMAScript spec]: //! [tsc]: //! [`Traverse`]: diff --git a/crates/oxc_codegen/src/comment.rs b/crates/oxc_codegen/src/comment.rs index 3365b2c11ecb96..cda260537f8e6f 100644 --- a/crates/oxc_codegen/src/comment.rs +++ b/crates/oxc_codegen/src/comment.rs @@ -39,7 +39,7 @@ impl<'a> Codegen<'a> { /// `#__PURE__` Notation Specification /// - /// + /// fn is_annotation_comment(&self, comment: &Comment) -> bool { let s = comment.content_span().source_text(self.source_text).trim_start(); if let Some(s) = s.strip_prefix(['@', '#']) { diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 06b29c25748bcd..a7f1cc4d9b8d72 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -67,7 +67,7 @@ impl<'a> Gen for Directive<'a> { p.print_indent(); // A Use Strict Directive may not contain an EscapeSequence or LineContinuation. // So here should print original `directive` value, the `expression` value is escaped str. - // See https://github.com/babel/babel/blob/main/packages/babel-generator/src/generators/base.ts#L64 + // See https://github.com/babel/babel/blob/v7.26.2/packages/babel-generator/src/generators/base.ts#L64 p.wrap_quote(|p, _| { p.print_str(self.directive.as_str()); }); diff --git a/crates/oxc_codegen/src/lib.rs b/crates/oxc_codegen/src/lib.rs index b55933a8de0d7e..28f5c684799a9d 100644 --- a/crates/oxc_codegen/src/lib.rs +++ b/crates/oxc_codegen/src/lib.rs @@ -1,7 +1,7 @@ //! Oxc Codegen //! //! Code adapted from -//! * [esbuild](https://github.com/evanw/esbuild/blob/main/internal/js_printer/js_printer.go) +//! * [esbuild](https://github.com/evanw/esbuild/blob/v0.24.0/internal/js_printer/js_printer.go) #![warn(missing_docs)] mod binary_expr_visitor; diff --git a/crates/oxc_codegen/tests/integration/esbuild.rs b/crates/oxc_codegen/tests/integration/esbuild.rs index 690afb13d8ae32..7dc42d806eceac 100644 --- a/crates/oxc_codegen/tests/integration/esbuild.rs +++ b/crates/oxc_codegen/tests/integration/esbuild.rs @@ -1,6 +1,6 @@ //! Tests ported from `esbuild` -//! * -//! * +//! * +//! * use crate::tester::{test, test_minify}; diff --git a/crates/oxc_codegen/tests/integration/pure_comments.rs b/crates/oxc_codegen/tests/integration/pure_comments.rs index 5ceb65abec09c3..8457d650ed80b4 100644 --- a/crates/oxc_codegen/tests/integration/pure_comments.rs +++ b/crates/oxc_codegen/tests/integration/pure_comments.rs @@ -133,7 +133,7 @@ const defineSSRCustomElement = () => { const Component = // #__PURE__ React.forwardRef((props, ref) => {}); ", - // Copy from + // Copy from " function bar() {} let bare = foo(bar); diff --git a/crates/oxc_codegen/tests/integration/unit.rs b/crates/oxc_codegen/tests/integration/unit.rs index d104e8989bd2c3..2dc4bd1e7cd9d1 100644 --- a/crates/oxc_codegen/tests/integration/unit.rs +++ b/crates/oxc_codegen/tests/integration/unit.rs @@ -59,7 +59,7 @@ fn shorthand() { test("let { x } = y", "let { x } = y;\n"); test("({ x: (x) })", "({ x });\n"); test("({ x } = y)", "({x} = y);\n"); - // https://github.com/tc39/test262/blob/main/test/language/expressions/object/__proto__-permitted-dup-shorthand.js + // https://github.com/tc39/test262/blob/05c45a4c430ab6fee3e0c7f0d47d8a30d8876a6d/test/language/expressions/object/__proto__-permitted-dup-shorthand.js test("var obj = { __proto__, __proto__, };", "var obj = {\n\t__proto__,\n\t__proto__\n};\n"); test("var obj = { __proto__: __proto__, };", "var obj = { __proto__: __proto__ };\n"); } diff --git a/crates/oxc_diagnostics/src/reporter/json.rs b/crates/oxc_diagnostics/src/reporter/json.rs index 2a52fe9767736f..c31b9ea383778d 100644 --- a/crates/oxc_diagnostics/src/reporter/json.rs +++ b/crates/oxc_diagnostics/src/reporter/json.rs @@ -27,7 +27,7 @@ impl DiagnosticReporter for JsonReporter { } } -/// +/// #[allow(clippy::print_stdout)] fn format_json(diagnostics: &mut Vec) { let handler = JSONReportHandler::new(); diff --git a/crates/oxc_diagnostics/src/reporter/unix.rs b/crates/oxc_diagnostics/src/reporter/unix.rs index e91bf5f2c4d963..a3e9ecaa2297ba 100644 --- a/crates/oxc_diagnostics/src/reporter/unix.rs +++ b/crates/oxc_diagnostics/src/reporter/unix.rs @@ -37,7 +37,7 @@ impl DiagnosticReporter for UnixReporter { } } -/// +/// fn format_unix(diagnostic: &Error) -> String { let Info { line, column, filename, message, severity, rule_id } = Info::new(diagnostic); let severity = match severity { diff --git a/crates/oxc_isolated_declarations/src/lib.rs b/crates/oxc_isolated_declarations/src/lib.rs index 2a834c0e5f267e..18c7e5ec369a9a 100644 --- a/crates/oxc_isolated_declarations/src/lib.rs +++ b/crates/oxc_isolated_declarations/src/lib.rs @@ -3,7 +3,7 @@ //! References: //! * //! * -//! * +//! * mod class; mod declaration; diff --git a/crates/oxc_isolated_declarations/tests/deno/mod.rs b/crates/oxc_isolated_declarations/tests/deno/mod.rs index b320b6738032cc..992fe918620c5f 100644 --- a/crates/oxc_isolated_declarations/tests/deno/mod.rs +++ b/crates/oxc_isolated_declarations/tests/deno/mod.rs @@ -1,4 +1,4 @@ -//! Copy from +//! Copy from //! Make some changes to conform to the Isolated Declarations output #[cfg(test)] diff --git a/crates/oxc_linter/src/config/settings/jsdoc.rs b/crates/oxc_linter/src/config/settings/jsdoc.rs index 3f8fe24d6e62ab..f8e3079935edc0 100644 --- a/crates/oxc_linter/src/config/settings/jsdoc.rs +++ b/crates/oxc_linter/src/config/settings/jsdoc.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; use crate::utils::default_true; -// +// #[derive(Debug, Clone, Deserialize, Serialize, JsonSchema)] #[cfg_attr(test, derive(PartialEq))] pub struct JSDocPluginSettings { @@ -123,7 +123,7 @@ impl JSDocPluginSettings { Some(Cow::Borrowed(message)) } _ => { - // https://github.com/gajus/eslint-plugin-jsdoc/blob/main/docs/settings.md#default-preferred-aliases + // https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.5.0/docs/settings.md#default-preferred-aliases let aliased_name = match original_name { "virtual" => "abstract", "extends" => "augments", diff --git a/crates/oxc_linter/src/fixer/fix.rs b/crates/oxc_linter/src/fixer/fix.rs index d2375ae65c4c9f..aeec3ce372cdc1 100644 --- a/crates/oxc_linter/src/fixer/fix.rs +++ b/crates/oxc_linter/src/fixer/fix.rs @@ -457,7 +457,7 @@ impl<'a> CompositeFix<'a> { // } /// Gets one fix from the fixes. If we retrieve multiple fixes, this merges those into one. - /// + /// pub fn normalize_fixes(self, source_text: &str) -> Fix<'a> { match self { CompositeFix::Single(fix) => fix, @@ -472,7 +472,7 @@ impl<'a> CompositeFix<'a> { /// 2. contains overlapped ranges /// 3. contains negative ranges (span.start > span.end) /// - /// + /// fn merge_fixes(fixes: Vec>, source_text: &str) -> Fix<'a> { let mut fixes = fixes; if fixes.is_empty() { diff --git a/crates/oxc_linter/src/fixer/mod.rs b/crates/oxc_linter/src/fixer/mod.rs index 0083f4d7100b38..8b8b0f212c4420 100644 --- a/crates/oxc_linter/src/fixer/mod.rs +++ b/crates/oxc_linter/src/fixer/mod.rs @@ -11,7 +11,7 @@ use crate::LintContext; /// Produces [`RuleFix`] instances. Inspired by ESLint's [`RuleFixer`]. /// -/// [`RuleFixer`]: https://github.com/eslint/eslint/blob/main/lib/linter/rule-fixer.js +/// [`RuleFixer`]: https://github.com/eslint/eslint/blob/v9.9.1/lib/linter/rule-fixer.js #[derive(Clone, Copy)] #[must_use] pub struct RuleFixer<'c, 'a: 'c> { @@ -671,7 +671,7 @@ mod test { } // Remain test caces picked from eslint - // + // // 1. Combining autofixes #[test] fn merge_fixes_into_one() { diff --git a/crates/oxc_linter/src/globals.rs b/crates/oxc_linter/src/globals.rs index 2b0ed497679262..ad642e1f518b3f 100644 --- a/crates/oxc_linter/src/globals.rs +++ b/crates/oxc_linter/src/globals.rs @@ -70,7 +70,7 @@ pub const VALID_ARIA_PROPS: phf::Set<&'static str> = phf_set! { /// set of valid ARIA role definitions /// Reference: -/// Reference: +/// Reference: pub const VALID_ARIA_ROLES: phf::Set<&'static str> = phf_set! { "alert", "alertdialog", @@ -355,7 +355,7 @@ pub const HTML_TAG: phf::Set<&'static str> = phf_set! { /// if it's not reserved, then it can have aria-* roles, states, and properties /// Reference: /// Reference: -/// Reference: +/// Reference: pub const RESERVED_HTML_TAG: phf::Set<&'static str> = phf_set! { "base", "col", diff --git a/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs b/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs index 5c78c3b462b3bf..ecadb97f30496e 100644 --- a/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs +++ b/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs @@ -132,7 +132,7 @@ impl Rule for ArrayCallbackReturn { } } -/// Code ported from [eslint](https://github.com/eslint/eslint/blob/main/lib/rules/array-callback-return.js) +/// Code ported from [eslint](https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/array-callback-return.js) /// We're currently on a `Function` or `ArrowFunctionExpression`, findout if it is an argument /// to the target array methods we're interested in. pub fn get_array_method_name<'a>( diff --git a/crates/oxc_linter/src/rules/eslint/no_control_regex.rs b/crates/oxc_linter/src/rules/eslint/no_control_regex.rs index d0b4d31590bdfd..e5865dd34a8695 100644 --- a/crates/oxc_linter/src/rules/eslint/no_control_regex.rs +++ b/crates/oxc_linter/src/rules/eslint/no_control_regex.rs @@ -297,7 +297,7 @@ mod tests { #[test] fn test() { // test cases taken from eslint. See: - // https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-control-regex.js + // https://github.com/eslint/eslint/blob/v9.9.1/tests/lib/rules/no-control-regex.js Tester::new( NoControlRegex::NAME, vec![ diff --git a/crates/oxc_linter/src/rules/eslint/no_empty_character_class.rs b/crates/oxc_linter/src/rules/eslint/no_empty_character_class.rs index 588a98876ef667..2a2c9189a085e8 100644 --- a/crates/oxc_linter/src/rules/eslint/no_empty_character_class.rs +++ b/crates/oxc_linter/src/rules/eslint/no_empty_character_class.rs @@ -1,5 +1,5 @@ use memchr::memchr2; -// Ported from https://github.com/eslint/eslint/blob/main/lib/rules/no-empty-character-class.js +// Ported from https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/no-empty-character-class.js use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; diff --git a/crates/oxc_linter/src/rules/eslint/no_eval.rs b/crates/oxc_linter/src/rules/eslint/no_eval.rs index dbe81ab82ee428..19ff16e0e524d4 100644 --- a/crates/oxc_linter/src/rules/eslint/no_eval.rs +++ b/crates/oxc_linter/src/rules/eslint/no_eval.rs @@ -1,4 +1,4 @@ -// Ported from https://github.com/eslint/eslint/tree/main/lib/rules/no-eval.js +// Ported from https://github.com/eslint/eslint/tree/v9.9.1/lib/rules/no-eval.js use oxc_ast::{ast::Expression, AstKind}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; diff --git a/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs b/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs index e6b6284edf58b2..2cc40c21df531b 100644 --- a/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs +++ b/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs @@ -164,7 +164,7 @@ impl Rule for NoObjCalls { #[test] fn test() { use crate::tester::Tester; - // see: https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-obj-calls.js + // see: https://github.com/eslint/eslint/blob/v9.9.1/tests/lib/rules/no-obj-calls.js let pass = vec![ ("const m = Math;", None), diff --git a/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs b/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs index bdfe638b015e41..befea169ab60fd 100644 --- a/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs +++ b/crates/oxc_linter/src/rules/eslint/no_useless_escape.rs @@ -179,7 +179,7 @@ fn check_character( * it only needs to be escaped in character classes if it's at the beginning of the character class. To * account for this, consider it to be a valid escape character outside of character classes, and filter * out '^' characters that appear at the start of a character class. - * (From ESLint source: https://github.com/eslint/eslint/blob/main/lib/rules/no-useless-escape.js) + * (From ESLint source: https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/no-useless-escape.js) */ if class.span.start + 1 == span.start { return None; @@ -216,7 +216,7 @@ fn check_character( * class, and is not at either edge of the character class. To account for this, don't consider '-' * characters to be valid in general, and filter out '-' characters that appear in the middle of a * character class. - * (From ESLint source: https://github.com/eslint/eslint/blob/main/lib/rules/no-useless-escape.js) + * (From ESLint source: https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/no-useless-escape.js) */ if class.span.start + 1 != span.start && span.end != class.span.end - 1 { return None; diff --git a/crates/oxc_linter/src/rules/eslint/no_var.rs b/crates/oxc_linter/src/rules/eslint/no_var.rs index 7f7bee97322e7f..a30e6d49373f19 100644 --- a/crates/oxc_linter/src/rules/eslint/no_var.rs +++ b/crates/oxc_linter/src/rules/eslint/no_var.rs @@ -17,9 +17,9 @@ fn no_var_diagnostic(span: Span) -> OxcDiagnostic { #[derive(Debug, Default, Clone)] pub struct NoVar; -// doc: https://github.com/eslint/eslint/blob/main/docs/src/rules/no-var.md -// code: https://github.com/eslint/eslint/blob/main/lib/rules/no-var.js -// test: https://github.com/eslint/eslint/blob/main/tests/lib/rules/no-var.js +// doc: https://github.com/eslint/eslint/blob/v9.9.1/docs/src/rules/no-var.md +// code: https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/no-var.js +// test: https://github.com/eslint/eslint/blob/v9.9.1/tests/lib/rules/no-var.js declare_oxc_lint!( /// ### What it does diff --git a/crates/oxc_linter/src/rules/eslint/radix.rs b/crates/oxc_linter/src/rules/eslint/radix.rs index 383c62ef2a18f3..d22e3e76c55c6d 100644 --- a/crates/oxc_linter/src/rules/eslint/radix.rs +++ b/crates/oxc_linter/src/rules/eslint/radix.rs @@ -31,9 +31,9 @@ pub struct Radix { radix_type: RadixType, } -// doc: https://github.com/eslint/eslint/blob/main/docs/src/rules/radix.md -// code: https://github.com/eslint/eslint/blob/main/lib/rules/radix.js -// test: https://github.com/eslint/eslint/blob/main/tests/lib/rules/radix.js +// doc: https://github.com/eslint/eslint/blob/v9.9.1/docs/src/rules/radix.md +// code: https://github.com/eslint/eslint/blob/v9.9.1/lib/rules/radix.js +// test: https://github.com/eslint/eslint/blob/v9.9.1/tests/lib/rules/radix.js declare_oxc_lint!( /// ### What it does diff --git a/crates/oxc_linter/src/rules/import/default.rs b/crates/oxc_linter/src/rules/import/default.rs index e15a84d877a354..0344138a4d4595 100644 --- a/crates/oxc_linter/src/rules/import/default.rs +++ b/crates/oxc_linter/src/rules/import/default.rs @@ -11,7 +11,7 @@ fn default_diagnostic(imported_name: &str, span: Span) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct Default; diff --git a/crates/oxc_linter/src/rules/import/export.rs b/crates/oxc_linter/src/rules/import/export.rs index db1edca4151425..cb79d91b35611a 100644 --- a/crates/oxc_linter/src/rules/import/export.rs +++ b/crates/oxc_linter/src/rules/import/export.rs @@ -13,7 +13,7 @@ fn no_named_export(module_name: &str, span: Span) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct Export; diff --git a/crates/oxc_linter/src/rules/import/first.rs b/crates/oxc_linter/src/rules/import/first.rs index 32c60e16078b2b..57ff1d6329a6d3 100644 --- a/crates/oxc_linter/src/rules/import/first.rs +++ b/crates/oxc_linter/src/rules/import/first.rs @@ -95,7 +95,7 @@ fn is_relative_path(path: &str) -> bool { path.starts_with("./") } -/// +/// impl Rule for First { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); diff --git a/crates/oxc_linter/src/rules/import/import_no_namespace.rs b/crates/oxc_linter/src/rules/import/import_no_namespace.rs index 44371dc8253689..09ede4e7b88de8 100644 --- a/crates/oxc_linter/src/rules/import/import_no_namespace.rs +++ b/crates/oxc_linter/src/rules/import/import_no_namespace.rs @@ -82,7 +82,7 @@ declare_oxc_lint!( pending // TODO: fixer ); -/// +/// impl Rule for ImportNoNamespace { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); diff --git a/crates/oxc_linter/src/rules/import/max_dependencies.rs b/crates/oxc_linter/src/rules/import/max_dependencies.rs index 44464735f05e0c..17bf68e302df8d 100644 --- a/crates/oxc_linter/src/rules/import/max_dependencies.rs +++ b/crates/oxc_linter/src/rules/import/max_dependencies.rs @@ -16,7 +16,7 @@ fn max_dependencies_diagnostic>>( .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct MaxDependencies(Box); diff --git a/crates/oxc_linter/src/rules/import/named.rs b/crates/oxc_linter/src/rules/import/named.rs index a1988ab3f88e50..6718339147f73f 100644 --- a/crates/oxc_linter/src/rules/import/named.rs +++ b/crates/oxc_linter/src/rules/import/named.rs @@ -11,7 +11,7 @@ fn named_diagnostic(imported_name: &str, module_name: &str, span: Span) -> OxcDi .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct Named; diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs index 8173e6886375f6..33a7a58e201e30 100644 --- a/crates/oxc_linter/src/rules/import/namespace.rs +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -42,7 +42,7 @@ fn assignment(span: Span, namespace_name: &str) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct Namespace { allow_computed: bool, diff --git a/crates/oxc_linter/src/rules/import/no_amd.rs b/crates/oxc_linter/src/rules/import/no_amd.rs index 1a5261c289eb4c..e62fed296f2bdd 100644 --- a/crates/oxc_linter/src/rules/import/no_amd.rs +++ b/crates/oxc_linter/src/rules/import/no_amd.rs @@ -47,7 +47,7 @@ declare_oxc_lint!( restriction ); -/// +/// impl Rule for NoAmd { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { // not in top level diff --git a/crates/oxc_linter/src/rules/import/no_commonjs.rs b/crates/oxc_linter/src/rules/import/no_commonjs.rs index 6411f5784dac13..0dc3151028d402 100644 --- a/crates/oxc_linter/src/rules/import/no_commonjs.rs +++ b/crates/oxc_linter/src/rules/import/no_commonjs.rs @@ -128,7 +128,7 @@ fn is_conditional(parent_node: &AstNode, ctx: &LintContext) -> bool { is_conditional(parent, ctx) } } -/// +/// impl Rule for NoCommonjs { fn from_configuration(value: serde_json::Value) -> Self { let obj = value.get(0); diff --git a/crates/oxc_linter/src/rules/import/no_cycle.rs b/crates/oxc_linter/src/rules/import/no_cycle.rs index 0487ee062736b2..8e62f28e29dcae 100644 --- a/crates/oxc_linter/src/rules/import/no_cycle.rs +++ b/crates/oxc_linter/src/rules/import/no_cycle.rs @@ -18,7 +18,7 @@ fn no_cycle_diagnostic(span: Span, paths: &str) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Clone)] pub struct NoCycle { /// maximum dependency depth to traverse diff --git a/crates/oxc_linter/src/rules/import/no_deprecated.rs b/crates/oxc_linter/src/rules/import/no_deprecated.rs index ee4020527c41f4..b4d2c766e02381 100644 --- a/crates/oxc_linter/src/rules/import/no_deprecated.rs +++ b/crates/oxc_linter/src/rules/import/no_deprecated.rs @@ -12,7 +12,7 @@ use crate::{ // #[diagnostic(severity(warning), help(""))] // struct NoDeprecatedDiagnostic(CompactStr, #[label] pub Span); -/// +/// #[derive(Debug, Default, Clone)] pub struct NoDeprecated; diff --git a/crates/oxc_linter/src/rules/import/no_duplicates.rs b/crates/oxc_linter/src/rules/import/no_duplicates.rs index d35ee702b9d1e4..5b37aa0db2cbad 100644 --- a/crates/oxc_linter/src/rules/import/no_duplicates.rs +++ b/crates/oxc_linter/src/rules/import/no_duplicates.rs @@ -32,7 +32,7 @@ where .with_help("Merge these imports into a single import statement") } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoDuplicates { prefer_inline: bool, diff --git a/crates/oxc_linter/src/rules/import/no_named_as_default.rs b/crates/oxc_linter/src/rules/import/no_named_as_default.rs index a6e352057775ba..5518e032d45113 100644 --- a/crates/oxc_linter/src/rules/import/no_named_as_default.rs +++ b/crates/oxc_linter/src/rules/import/no_named_as_default.rs @@ -15,7 +15,7 @@ fn no_named_as_default_diagnostic( .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoNamedAsDefault; diff --git a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs index b34349de518c52..65e5b2ece28d5a 100644 --- a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs +++ b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs @@ -22,7 +22,7 @@ fn no_named_as_default_member_dignostic( .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoNamedAsDefaultMember; diff --git a/crates/oxc_linter/src/rules/import/no_unused_modules.rs b/crates/oxc_linter/src/rules/import/no_unused_modules.rs index 8a4dd3f19a5a59..f1880a755235ba 100644 --- a/crates/oxc_linter/src/rules/import/no_unused_modules.rs +++ b/crates/oxc_linter/src/rules/import/no_unused_modules.rs @@ -10,7 +10,7 @@ fn no_exports_found(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("No exports found").with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoUnusedModules { missing_exports: bool, diff --git a/crates/oxc_linter/src/rules/import/unambiguous.rs b/crates/oxc_linter/src/rules/import/unambiguous.rs index 810fb9b023802b..248c3e87272880 100644 --- a/crates/oxc_linter/src/rules/import/unambiguous.rs +++ b/crates/oxc_linter/src/rules/import/unambiguous.rs @@ -45,7 +45,7 @@ declare_oxc_lint!( restriction ); -/// +/// impl Rule for Unambiguous { fn run_once(&self, ctx: &LintContext<'_>) { if ctx.semantic().module_record().not_esm { diff --git a/crates/oxc_linter/src/rules/jest/consistent_test_it.rs b/crates/oxc_linter/src/rules/jest/consistent_test_it.rs index 2c5bfe0ad1290e..657e245c701125 100644 --- a/crates/oxc_linter/src/rules/jest/consistent_test_it.rs +++ b/crates/oxc_linter/src/rules/jest/consistent_test_it.rs @@ -158,7 +158,7 @@ declare_oxc_lint!( /// Decides whether to use `test` or `it` within a `describe` scope. /// /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/consistent-test-it.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/consistent-test-it.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/expect_expect.rs b/crates/oxc_linter/src/rules/jest/expect_expect.rs index 9251d001c07eb9..c95e72c1fffd79 100644 --- a/crates/oxc_linter/src/rules/jest/expect_expect.rs +++ b/crates/oxc_linter/src/rules/jest/expect_expect.rs @@ -68,7 +68,7 @@ declare_oxc_lint!( /// test('should assert something', () => {}); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/expect-expect.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/expect-expect.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_alias_methods.rs b/crates/oxc_linter/src/rules/jest/no_alias_methods.rs index 291492107c82ac..5a53652955cda3 100644 --- a/crates/oxc_linter/src/rules/jest/no_alias_methods.rs +++ b/crates/oxc_linter/src/rules/jest/no_alias_methods.rs @@ -43,7 +43,7 @@ declare_oxc_lint!( /// expect(a).toThrowError(); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-alias-methods.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-alias-methods.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs b/crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs index 85a61bae6f6bef..05f8115e42853f 100644 --- a/crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs +++ b/crates/oxc_linter/src/rules/jest/no_commented_out_tests.rs @@ -38,7 +38,7 @@ declare_oxc_lint!( /// // test.skip('foo', () => {}); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-commented-out-tests.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-commented-out-tests.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs b/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs index 0ef65084e2d823..27c08a317154a9 100644 --- a/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs +++ b/crates/oxc_linter/src/rules/jest/no_conditional_expect.rs @@ -51,7 +51,7 @@ declare_oxc_lint!( /// }); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-conditional-expect.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-conditional-expect.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs b/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs index 6b5b667991acb4..f0275a7289631e 100644 --- a/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs +++ b/crates/oxc_linter/src/rules/jest/no_disabled_tests.rs @@ -49,7 +49,7 @@ declare_oxc_lint!( /// }); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-disabled-tests.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-disabled-tests.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_focused_tests.rs b/crates/oxc_linter/src/rules/jest/no_focused_tests.rs index f598b879bd0b86..317254c0b0db3f 100644 --- a/crates/oxc_linter/src/rules/jest/no_focused_tests.rs +++ b/crates/oxc_linter/src/rules/jest/no_focused_tests.rs @@ -50,7 +50,7 @@ declare_oxc_lint!( /// `(); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-focused-tests.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-focused-tests.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_identical_title.rs b/crates/oxc_linter/src/rules/jest/no_identical_title.rs index 5a91f89d4d5c2b..251b55c6cf38d0 100644 --- a/crates/oxc_linter/src/rules/jest/no_identical_title.rs +++ b/crates/oxc_linter/src/rules/jest/no_identical_title.rs @@ -56,7 +56,7 @@ declare_oxc_lint!( /// }); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-identical-title.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-identical-title.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs index 28948fab702d3c..fc7b126e0b1cd8 100644 --- a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs +++ b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs @@ -14,7 +14,7 @@ fn no_jasmine_globals_diagnostic(x0: &str, x1: &str, span2: Span) -> OxcDiagnost OxcDiagnostic::warn(format!("{x0:?}")).with_help(format!("{x1:?}")).with_label(span2) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoJasmineGlobals; diff --git a/crates/oxc_linter/src/rules/jest/no_mocks_import.rs b/crates/oxc_linter/src/rules/jest/no_mocks_import.rs index 6fc5d1fda8d7cf..6b11fd34ff0383 100644 --- a/crates/oxc_linter/src/rules/jest/no_mocks_import.rs +++ b/crates/oxc_linter/src/rules/jest/no_mocks_import.rs @@ -13,7 +13,7 @@ fn no_mocks_import_diagnostic(span: Span) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoMocksImport; diff --git a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs index b9eebaf72a7208..04b92f236ff6b0 100644 --- a/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs +++ b/crates/oxc_linter/src/rules/jest/no_standalone_expect.rs @@ -22,7 +22,7 @@ fn no_standalone_expect_diagnostic(span: Span) -> OxcDiagnostic { .with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoStandaloneExpect(Box); diff --git a/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs b/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs index 636b02c57ec48c..d76bc9902093f4 100644 --- a/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs +++ b/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs @@ -42,7 +42,7 @@ declare_oxc_lint!( /// xdescribe('foo'); // invalid /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/no-test-prefixes.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/no-test-prefixes.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/prefer_hooks_in_order.rs b/crates/oxc_linter/src/rules/jest/prefer_hooks_in_order.rs index e16941dc0e6ee3..ff532302a3c89d 100644 --- a/crates/oxc_linter/src/rules/jest/prefer_hooks_in_order.rs +++ b/crates/oxc_linter/src/rules/jest/prefer_hooks_in_order.rs @@ -128,7 +128,7 @@ declare_oxc_lint!( /// ``` /// /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/prefer-hooks-in-order.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/prefer-hooks-in-order.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/valid_describe_callback.rs b/crates/oxc_linter/src/rules/jest/valid_describe_callback.rs index 86fb024d1ab404..4914a0318d4393 100644 --- a/crates/oxc_linter/src/rules/jest/valid_describe_callback.rs +++ b/crates/oxc_linter/src/rules/jest/valid_describe_callback.rs @@ -58,7 +58,7 @@ declare_oxc_lint!( /// })); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/valid-describe-callback.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/valid-describe-callback.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jest/valid_expect.rs b/crates/oxc_linter/src/rules/jest/valid_expect.rs index 938fdf3840d665..7f63d91ea00abc 100644 --- a/crates/oxc_linter/src/rules/jest/valid_expect.rs +++ b/crates/oxc_linter/src/rules/jest/valid_expect.rs @@ -68,7 +68,7 @@ declare_oxc_lint!( /// expect(Promise.resolve('Hi!')).resolves.toBe('Hi!'); /// ``` /// - /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/main/docs/rules/valid-expect.md), + /// This rule is compatible with [eslint-plugin-vitest](https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/docs/rules/valid-expect.md), /// to use it, add the following configuration to your `.eslintrc.json`: /// /// ```json diff --git a/crates/oxc_linter/src/rules/jsx_a11y/lang.rs b/crates/oxc_linter/src/rules/jsx_a11y/lang.rs index 0cf7d34f41cbf1..f42b1a2ea4e9b1 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/lang.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/lang.rs @@ -51,7 +51,7 @@ declare_oxc_lint!( /// ``` /// /// ### Resources - /// - [eslint-plugin-jsx-a11y/lang](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/lang.md) + /// - [eslint-plugin-jsx-a11y/lang](https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.9.0/docs/rules/lang.md) /// - [IANA Language Subtag Registry](https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry) Lang, correctness diff --git a/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs b/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs index d81d4547ab223b..7f2080d872a9aa 100644 --- a/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs +++ b/crates/oxc_linter/src/rules/jsx_a11y/role_supports_aria_props.rs @@ -100,7 +100,7 @@ impl Rule for RoleSupportsAriaProps { } } -/// ref: +/// ref: fn get_implicit_role<'a>( node: &'a JSXOpeningElement<'a>, element_type: &str, diff --git a/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs b/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs index d3ad356b5fc9e0..b5c3fb7fc05c3b 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_unwanted_polyfillio.rs @@ -38,7 +38,7 @@ declare_oxc_lint!( correctness ); -// Keep in sync with next.js polyfills file : https://github.com/vercel/next.js/blob/master/packages/next-polyfill-nomodule/src/index.js +// Keep in sync with next.js polyfills file : https://github.com/vercel/next.js/blob/v15.0.2/packages/next-polyfill-nomodule/src/index.js const NEXT_POLYFILLED_FEATURES: Set<&'static str> = phf_set! { "Array.prototype.@@iterator", "Array.prototype.at", diff --git a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs index f9c89409746826..d0a6fa0fbcb72c 100644 --- a/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs +++ b/crates/oxc_linter/src/rules/oxc/no_accumulating_spread.rs @@ -365,7 +365,7 @@ fn test() { } } ", - // source: https://github.com/biomejs/biome/blob/main/crates/biome_js_analyze/tests/specs/performance/noAccumulatingSpread/valid.jsonc#L3C1-L23C52 + // source: https://github.com/biomejs/biome/blob/cli/v1.9.4/crates/biome_js_analyze/tests/specs/performance/noAccumulatingSpread/valid.jsonc#L3C1-L23C52 "foo.reduce((acc, bar) => {acc.push(bar); return acc;}, [])", "foo.reduceRight((acc, bar) => {acc.push(bar); return acc;}, [])", // Array - Allow spreading the item into the accumulator @@ -420,7 +420,7 @@ fn test() { let temp = { ...acc, x } return temp }, {})", - // source https://github.com/biomejs/biome/blob/main/crates/biome_js_analyze/tests/specs/performance/noAccumulatingSpread/invalid.jsonc#L2-L32 + // source https://github.com/biomejs/biome/blob/cli/v1.9.4/crates/biome_js_analyze/tests/specs/performance/noAccumulatingSpread/invalid.jsonc#L2-L32 // Array - Arrow return "foo.reduce((acc, bar) => [...acc, bar], [])", "foo.reduceRight((acc, bar) => [...acc, bar], [])", diff --git a/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs b/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs index c6baacfa659a70..ccd7e9d8163f9c 100644 --- a/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs +++ b/crates/oxc_linter/src/rules/react/no_direct_mutation_state.rs @@ -22,9 +22,9 @@ fn no_direct_mutation_state_diagnostic(span: Span) -> OxcDiagnostic { #[derive(Debug, Default, Clone)] pub struct NoDirectMutationState; -// code: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/lib/rules/no-direct-mutation-state.js -// doc: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/docs/rules/no-direct-mutation-state.md -// test: https://github.com/jsx-eslint/eslint-plugin-react/blob/master/tests/lib/rules/no-direct-mutation-state.js +// code: https://github.com/jsx-eslint/eslint-plugin-react/blob/v7.37.2/lib/rules/no-direct-mutation-state.js +// doc: https://github.com/jsx-eslint/eslint-plugin-react/blob/v7.37.2/docs/rules/no-direct-mutation-state.md +// test: https://github.com/jsx-eslint/eslint-plugin-react/blob/v7.37.2/tests/lib/rules/no-direct-mutation-state.js declare_oxc_lint!( /// ### What it does diff --git a/crates/oxc_linter/src/rules/security/api_keys/mod.rs b/crates/oxc_linter/src/rules/security/api_keys/mod.rs index 3cc7178726d530..936e5e1392e004 100644 --- a/crates/oxc_linter/src/rules/security/api_keys/mod.rs +++ b/crates/oxc_linter/src/rules/security/api_keys/mod.rs @@ -72,7 +72,7 @@ declare_oxc_lint!( /// One possible alternative is to store secrets in a secure secrets manager /// (such as [AWS /// KMS](https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/kms/), - /// [HashiCorp Vault](https://github.com/nodevault/node-vault/tree/master), + /// [HashiCorp Vault](https://github.com/nodevault/node-vault/tree/v0.10.2), /// [Pangea](https://pangea.cloud/docs/sdk/js/vault#retrieve), etc.) and /// request them when your application starts (e.g. a Docker container, an /// EC2). 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 9d82923d225f0e..be2dab30c97f28 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 @@ -88,7 +88,7 @@ fn throw(span: Span) -> OxcDiagnostic { OxcDiagnostic::warn("Throwing an error is a side-effect").with_label(span) } -/// +/// #[derive(Debug, Default, Clone)] pub struct NoSideEffectsInInitialization(Box); diff --git a/crates/oxc_linter/src/rules/typescript/consistent_type_imports.rs b/crates/oxc_linter/src/rules/typescript/consistent_type_imports.rs index 49f81db637415b..13f1603b5fbbbb 100644 --- a/crates/oxc_linter/src/rules/typescript/consistent_type_imports.rs +++ b/crates/oxc_linter/src/rules/typescript/consistent_type_imports.rs @@ -47,7 +47,7 @@ impl Deref for ConsistentTypeImports { } } -/// +/// #[derive(Default, Debug, Clone)] pub struct ConsistentTypeImportsConfig { disallow_type_annotations: DisallowTypeAnnotations, diff --git a/crates/oxc_linter/src/utils/react.rs b/crates/oxc_linter/src/utils/react.rs index 1fcd235c16849d..ff9bf38f79a627 100644 --- a/crates/oxc_linter/src/utils/react.rs +++ b/crates/oxc_linter/src/utils/react.rs @@ -60,7 +60,7 @@ pub fn get_string_literal_prop_value<'a>(item: &'a JSXAttributeItem<'_>) -> Opti get_prop_value(item).and_then(JSXAttributeValue::as_string_literal).map(|s| s.value.as_str()) } -// ref: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/util/isHiddenFromScreenReader.js +// ref: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.9.0/src/util/isHiddenFromScreenReader.js pub fn is_hidden_from_screen_reader<'a>( ctx: &LintContext<'a>, node: &JSXOpeningElement<'a>, @@ -91,7 +91,7 @@ pub fn is_hidden_from_screen_reader<'a>( }) } -// ref: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/util/hasAccessibleChild.js +// ref: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.9.0/src/util/hasAccessibleChild.js pub fn object_has_accessible_child<'a>(ctx: &LintContext<'a>, node: &JSXElement<'a>) -> bool { node.children.iter().any(|child| match child { JSXChild::Text(text) => !text.value.is_empty(), @@ -206,7 +206,7 @@ pub fn get_parent_component<'a, 'b>( /// Resolve element type(name) using jsx-a11y settings /// ref: -/// +/// pub fn get_element_type<'c, 'a>( context: &'c LintContext<'a>, element: &JSXOpeningElement<'a>, diff --git a/crates/oxc_linter/src/utils/unicorn.rs b/crates/oxc_linter/src/utils/unicorn.rs index 3806039ddb34e7..77e5c5d65bd5bf 100644 --- a/crates/oxc_linter/src/utils/unicorn.rs +++ b/crates/oxc_linter/src/utils/unicorn.rs @@ -39,7 +39,7 @@ pub fn is_empty_stmt(stmt: &Statement) -> bool { } } -// ref: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/rules/utils/array-or-object-prototype-property.js +// ref: https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v56.0.0/rules/utils/array-or-object-prototype-property.js pub fn is_prototype_property( member_expr: &MemberExpression, property: &str, diff --git a/crates/oxc_mangler/src/lib.rs b/crates/oxc_mangler/src/lib.rs index dfabd1e431ebb1..cb6b085cb14be1 100644 --- a/crates/oxc_mangler/src/lib.rs +++ b/crates/oxc_mangler/src/lib.rs @@ -14,7 +14,7 @@ pub struct MangleOptions { /// # Name Mangler / Symbol Minification /// /// See: -/// * [esbuild](https://github.com/evanw/esbuild/blob/main/docs/architecture.md#symbol-minification) +/// * [esbuild](https://github.com/evanw/esbuild/blob/v0.24.0/docs/architecture.md#symbol-minification) /// /// This algorithm is targeted for better gzip compression. /// diff --git a/crates/oxc_minifier/README.md b/crates/oxc_minifier/README.md index f88e8ca6f2422f..68b504ed7b4d61 100644 --- a/crates/oxc_minifier/README.md +++ b/crates/oxc_minifier/README.md @@ -20,4 +20,4 @@ The compressor is responsible for rewriting statements and expressions for minim ## Terser Tests -The fixtures are copied from https://github.com/terser/terser/tree/master/test/compress +The fixtures are copied from https://github.com/terser/terser/tree/v5.9.0/test/compress diff --git a/crates/oxc_minifier/src/ast_passes/collapse_variable_declarations.rs b/crates/oxc_minifier/src/ast_passes/collapse_variable_declarations.rs index c7e9de1c449cd5..dd074e7a4c5bd6 100644 --- a/crates/oxc_minifier/src/ast_passes/collapse_variable_declarations.rs +++ b/crates/oxc_minifier/src/ast_passes/collapse_variable_declarations.rs @@ -7,7 +7,7 @@ use crate::CompressorPass; /// Collapse variable declarations. /// /// `var a; var b = 1; var c = 2` => `var a, b = 1; c = 2` -/// +/// pub struct CollapseVariableDeclarations { changed: bool, } @@ -108,7 +108,7 @@ impl<'a> CollapseVariableDeclarations { } } -/// +/// #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/exploit_assigns.rs b/crates/oxc_minifier/src/ast_passes/exploit_assigns.rs index 84b5783b13b756..50558bd8cc4a85 100644 --- a/crates/oxc_minifier/src/ast_passes/exploit_assigns.rs +++ b/crates/oxc_minifier/src/ast_passes/exploit_assigns.rs @@ -5,7 +5,7 @@ use crate::CompressorPass; /// Tries to chain assignments together. /// -/// +/// pub struct ExploitAssigns { changed: bool, } @@ -29,7 +29,7 @@ impl ExploitAssigns { } } -/// +/// #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index d7397ff5c24358..282ddbe102f835 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -14,7 +14,7 @@ use crate::{node_util::Ctx, CompressorPass}; /// Constant Folding /// -/// +/// pub struct PeepholeFoldConstants { changed: bool, } @@ -449,7 +449,7 @@ impl<'a, 'b> PeepholeFoldConstants { } } -/// +/// #[cfg(test)] mod test { use oxc_allocator::Allocator; @@ -1158,7 +1158,7 @@ mod test { test("1 << -1", "1<<-1"); test("1 >> 32", "1>>32"); - // Regression on #6161, ported from . + // Regression on #6161, ported from . test("-2147483647 >>> 0", "2147483649"); test("-2147483648 >>> 0", "2147483648"); test("-2147483649 >>> 0", "2147483647"); diff --git a/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs b/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs index 8bcd18bbf2e25b..1b0bb1bbea176a 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_minimize_conditions.rs @@ -9,7 +9,7 @@ use crate::CompressorPass; /// Also rewrites conditional statements as expressions by replacing them /// with `? :` and short-circuit binary operators. /// -/// +/// pub struct PeepholeMinimizeConditions { changed: bool, } @@ -58,7 +58,7 @@ impl<'a> PeepholeMinimizeConditions { } } -/// +/// #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs index 3f9c1d1d30b02a..e92be6327d3b7f 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_remove_dead_code.rs @@ -12,7 +12,7 @@ use crate::{keep_var::KeepVar, CompressorPass}; /// Terser option: `dead_code: true`. /// /// See `KeepVar` at the end of this file for `var` hoisting logic. -/// +/// pub struct PeepholeRemoveDeadCode { changed: bool, } @@ -417,7 +417,7 @@ impl<'a, 'b> PeepholeRemoveDeadCode { } } -/// +/// #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/peephole_replace_known_methods.rs b/crates/oxc_minifier/src/ast_passes/peephole_replace_known_methods.rs index 5b9e67a5da11aa..4a8b044b0a74f9 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_replace_known_methods.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_replace_known_methods.rs @@ -9,7 +9,7 @@ use oxc_traverse::{Traverse, TraverseCtx}; use crate::{node_util::Ctx, CompressorPass}; /// Minimize With Known Methods -/// +/// pub struct PeepholeReplaceKnownMethods { changed: bool, } @@ -269,7 +269,7 @@ impl PeepholeReplaceKnownMethods { } } -/// Port from: +/// Port from: #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs index 381db25a375e0f..dcd52b3eb3e570 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_substitute_alternate_syntax.rs @@ -14,7 +14,7 @@ use crate::{node_util::Ctx, CompressorPass}; /// A peephole optimization that minimizes code by simplifying conditional /// expressions, replacing IFs with HOOKs, replacing object constructors /// with literals, and simplifying returns. -/// +/// pub struct PeepholeSubstituteAlternateSyntax { /// Do not compress syntaxes that are hard to analyze inside the fixed loop. /// e.g. Do not compress `undefined -> void 0`, `true` -> `!0`. @@ -566,7 +566,7 @@ impl<'a, 'b> PeepholeSubstituteAlternateSyntax { } } -/// Port from +/// Port from #[cfg(test)] mod test { use oxc_allocator::Allocator; diff --git a/crates/oxc_minifier/src/ast_passes/statement_fusion.rs b/crates/oxc_minifier/src/ast_passes/statement_fusion.rs index 05531760ae57f3..3b3e497639838d 100644 --- a/crates/oxc_minifier/src/ast_passes/statement_fusion.rs +++ b/crates/oxc_minifier/src/ast_passes/statement_fusion.rs @@ -10,7 +10,7 @@ use crate::CompressorPass; /// /// Tries to fuse all the statements in a block into a one statement by using COMMAs or statements. /// -/// +/// pub struct StatementFusion { changed: bool, } diff --git a/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs b/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs index 6b5e777fc29d89..f366e3fc60ae0a 100644 --- a/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs +++ b/crates/oxc_minifier/tests/ast_passes/dead_code_elimination.rs @@ -155,7 +155,7 @@ fn dce_var_hoisting() { ); } -// https://github.com/terser/terser/blob/master/test/compress/dead-code.js +// https://github.com/terser/terser/blob/v5.9.0/test/compress/dead-code.js #[test] fn dce_from_terser() { test( diff --git a/crates/oxc_module_lexer/tests/integration/esm.rs b/crates/oxc_module_lexer/tests/integration/esm.rs index 2e84808cedd8b5..618d0410e21c10 100644 --- a/crates/oxc_module_lexer/tests/integration/esm.rs +++ b/crates/oxc_module_lexer/tests/integration/esm.rs @@ -1,4 +1,4 @@ -//! +//! use oxc_allocator::Allocator; use oxc_module_lexer::ImportType; diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index 5a668fe4d63ec5..12e61c17f79c37 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -48,7 +48,7 @@ impl<'a> ParserImpl<'a> { // Section 11.2.1 Directive Prologue // The only way to get a correct directive is to parse the statement first and check if it is a string literal. - // All other method are flawed, see test cases in [babel](https://github.com/babel/babel/blob/main/packages/babel-parser/test/fixtures/core/categorized/not-directive/input.js) + // All other method are flawed, see test cases in [babel](https://github.com/babel/babel/blob/v7.26.2/packages/babel-parser/test/fixtures/core/categorized/not-directive/input.js) if expecting_directives { if let Statement::ExpressionStatement(expr) = &stmt { if let Expression::StringLiteral(string) = &expr.expression { diff --git a/crates/oxc_parser/src/lexer/byte_handlers.rs b/crates/oxc_parser/src/lexer/byte_handlers.rs index b7102a89fa8cff..140b60b6aced83 100644 --- a/crates/oxc_parser/src/lexer/byte_handlers.rs +++ b/crates/oxc_parser/src/lexer/byte_handlers.rs @@ -15,7 +15,7 @@ pub(super) unsafe fn handle_byte(byte: u8, lexer: &mut Lexer) -> Kind { type ByteHandler = unsafe fn(&mut Lexer<'_>) -> Kind; /// Lookup table mapping any incoming byte to a handler function defined below. -/// +/// #[rustfmt::skip] static BYTE_HANDLERS: [ByteHandler; 256] = [ // 0 1 2 3 4 5 6 7 8 9 A B C D E F // diff --git a/crates/oxc_parser/src/lexer/mod.rs b/crates/oxc_parser/src/lexer/mod.rs index 1e11d5b619e5d0..35ba4cb5b663a0 100644 --- a/crates/oxc_parser/src/lexer/mod.rs +++ b/crates/oxc_parser/src/lexer/mod.rs @@ -3,9 +3,9 @@ //! An Ecma-262 Lexer / Tokenizer //! Prior Arts: -//! * [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/parser/src) -//! * [rome](https://github.com/rome/tools/tree/main/crates/rome_js_parser/src/lexer) -//! * [rustc](https://github.com/rust-lang/rust/blob/master/compiler/rustc_lexer/src) +//! * [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/parser/src) +//! * [rome](https://github.com/rome/tools/tree/lsp/v0.28.0/crates/rome_js_parser/src/lexer) +//! * [rustc](https://github.com/rust-lang/rust/blob/1.82.0/compiler/rustc_lexer/src) //! * [v8](https://v8.dev/blog/scanner) mod byte_handlers; diff --git a/crates/oxc_parser/src/lexer/number.rs b/crates/oxc_parser/src/lexer/number.rs index c69df154f49fde..6fda36de5410c1 100644 --- a/crates/oxc_parser/src/lexer/number.rs +++ b/crates/oxc_parser/src/lexer/number.rs @@ -1,6 +1,6 @@ //! Parsing utilities for converting Javascript numbers to Rust f64. //! Code copied originally from -//! [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/master/crates/parser/src/numeric_value.rs) +//! [jsparagus](https://github.com/mozilla-spidermonkey/jsparagus/blob/24004745a8ed4939fc0dc7332bfd1268ac52285f/crates/parser/src/numeric_value.rs) //! but iterated on since. use std::borrow::Cow; diff --git a/crates/oxc_prettier/README.md b/crates/oxc_prettier/README.md index 947e226a876ad2..4382114e4fec35 100644 --- a/crates/oxc_prettier/README.md +++ b/crates/oxc_prettier/README.md @@ -7,4 +7,4 @@ Create a `test.js` and run the example `just example prettier` from `crates/oxc_ - [x] Have the basic infrastructure ready for contribution - [x] Implement a test runner in Rust which extracts the snapshots and do a comparison over it - [x] Establish a way to pass all the tests by manually porting code -- [ ] Pass as many tests as possible in https://github.com/prettier/prettier/tree/main/tests/format/js +- [ ] Pass as many tests as possible in https://github.com/prettier/prettier/tree/3.3.3/tests/format/js diff --git a/crates/oxc_prettier/src/doc.rs b/crates/oxc_prettier/src/doc.rs index 417d7a3e78fc90..651e0922a5d377 100644 --- a/crates/oxc_prettier/src/doc.rs +++ b/crates/oxc_prettier/src/doc.rs @@ -1,7 +1,7 @@ //! Prettier IR //! //! References: -//! * +//! * use std::fmt; @@ -218,7 +218,7 @@ impl<'a> fmt::Display for Doc<'a> { } } -// https://github.com/prettier/prettier/blob/main/src/document/debug.js +// https://github.com/prettier/prettier/blob/3.3.3/src/document/debug.js fn print_doc_to_debug(doc: &Doc<'_>) -> std::string::String { use std::string::String; let mut string = String::new(); diff --git a/crates/oxc_prettier/src/format/call_arguments.rs b/crates/oxc_prettier/src/format/call_arguments.rs index fcc278320fa0ee..3845dda8baf8b9 100644 --- a/crates/oxc_prettier/src/format/call_arguments.rs +++ b/crates/oxc_prettier/src/format/call_arguments.rs @@ -178,7 +178,7 @@ pub fn print_call_arguments<'a>( Doc::Group(Group::new(parts).with_break(should_break)) } -/// * Reference +/// * Reference fn should_expand_first_arg<'a>(arguments: &Vec<'a, Argument<'a>>) -> bool { if arguments.len() != 2 { return false; diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index bf2e9f9eb11050..d1c794111cbbd0 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -1,7 +1,7 @@ //! Formatting logic //! //! References: -//! * +//! * #![allow(unused_variables)] @@ -1789,7 +1789,7 @@ impl<'a> Format<'a> for NullLiteral { impl<'a> Format<'a> for NumericLiteral<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { wrap!(p, self, NumericLiteral, { - // See https://github.com/prettier/prettier/blob/main/src/utils/print-number.js + // See https://github.com/prettier/prettier/blob/3.3.3/src/utils/print-number.js // Perf: the regexes from prettier code above are ported to manual search for performance reasons. let mut string = self.span.source_text(p.source_text).cow_to_ascii_lowercase(); diff --git a/crates/oxc_prettier/src/lib.rs b/crates/oxc_prettier/src/lib.rs index d82ecfddf139f1..fe09665c3e184b 100644 --- a/crates/oxc_prettier/src/lib.rs +++ b/crates/oxc_prettier/src/lib.rs @@ -54,7 +54,7 @@ pub struct Prettier<'a> { options: PrettierOptions, /// The stack of AST Nodes - /// See + /// See stack: Vec>, group_id_builder: GroupIdBuilder, diff --git a/crates/oxc_prettier/src/needs_parens.rs b/crates/oxc_prettier/src/needs_parens.rs index 1698ec3b427599..71a65e8e8b62d0 100644 --- a/crates/oxc_prettier/src/needs_parens.rs +++ b/crates/oxc_prettier/src/needs_parens.rs @@ -1,6 +1,6 @@ //! Direct port of needs-parens for adding or removing parentheses. //! -//! See +//! See #![allow( clippy::unused_self, diff --git a/crates/oxc_prettier/src/options.rs b/crates/oxc_prettier/src/options.rs index b9f36f41e62e6a..53dda9bfec5d1a 100644 --- a/crates/oxc_prettier/src/options.rs +++ b/crates/oxc_prettier/src/options.rs @@ -4,8 +4,8 @@ use std::str::FromStr; /// /// References /// * -/// * -/// * +/// * +/// * #[derive(Debug, Clone, Copy)] pub struct PrettierOptions { /* Global Options */ diff --git a/crates/oxc_prettier/src/printer/mod.rs b/crates/oxc_prettier/src/printer/mod.rs index d3103cbfe1e10c..35525a90e69185 100644 --- a/crates/oxc_prettier/src/printer/mod.rs +++ b/crates/oxc_prettier/src/printer/mod.rs @@ -1,7 +1,7 @@ //! [Doc] Printer //! //! References: -//! * +//! * mod command; @@ -440,7 +440,7 @@ impl<'a> Printer<'a> { } /// Reference: - /// * + /// * pub fn propagate_breaks(doc: &mut Doc<'_>) -> bool { let check_array = |arr: &mut oxc_allocator::Vec<'_, Doc<'_>>| { arr.iter_mut().rev().any(|doc| Self::propagate_breaks(doc)) diff --git a/crates/oxc_sourcemap/src/decode.rs b/crates/oxc_sourcemap/src/decode.rs index fcbbc06f3fbe03..95ff8fff46bb74 100644 --- a/crates/oxc_sourcemap/src/decode.rs +++ b/crates/oxc_sourcemap/src/decode.rs @@ -1,11 +1,11 @@ -/// Port from https://github.com/getsentry/rust-sourcemap/blob/master/src/decoder.rs +/// Port from https://github.com/getsentry/rust-sourcemap/blob/9.1.0/src/decoder.rs /// It is a helper for decode vlq soucemap string to `SourceMap`. use std::sync::Arc; use crate::error::{Error, Result}; use crate::{SourceMap, Token}; -/// See . +/// See . #[derive(serde::Deserialize, Default)] #[serde(rename_all = "camelCase")] pub struct JSONSourceMap { diff --git a/crates/oxc_sourcemap/src/encode.rs b/crates/oxc_sourcemap/src/encode.rs index 356ce4f1e6df89..7bc27686a2068f 100644 --- a/crates/oxc_sourcemap/src/encode.rs +++ b/crates/oxc_sourcemap/src/encode.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use rayon::prelude::*; use crate::JSONSourceMap; -/// Port from https://github.com/getsentry/rust-sourcemap/blob/master/src/encoder.rs +/// Port from https://github.com/getsentry/rust-sourcemap/blob/9.1.0/src/encoder.rs /// It is a helper for encode `SourceMap` to vlq sourcemap string, but here some different. /// - Quote `source_content` at parallel. /// - If you using `ConcatSourceMapBuilder`, serialize `tokens` to vlq `mappings` at parallel. diff --git a/crates/oxc_transformer/src/common/helper_loader.rs b/crates/oxc_transformer/src/common/helper_loader.rs index 10e3a3c62452ce..a4ba256f342eb8 100644 --- a/crates/oxc_transformer/src/common/helper_loader.rs +++ b/crates/oxc_transformer/src/common/helper_loader.rs @@ -31,7 +31,7 @@ //! helperName(...arguments); //! ``` //! -//! Based on [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/main/packages/babel-plugin-transform-runtime). +//! Based on [@babel/plugin-transform-runtime](https://github.com/babel/babel/tree/v7.26.2/packages/babel-plugin-transform-runtime). //! //! ### External ([`HelperLoaderMode::External`]) //! @@ -43,7 +43,7 @@ //! babelHelpers.helperName(...arguments); //! ``` //! -//! Based on [@babel/plugin-external-helpers](https://github.com/babel/babel/tree/main/packages/babel-plugin-external-helpers). +//! Based on [@babel/plugin-external-helpers](https://github.com/babel/babel/tree/v7.26.2/packages/babel-plugin-external-helpers). //! //! ### Inline ([`HelperLoaderMode::Inline`]) //! @@ -58,7 +58,7 @@ //! helperName(...arguments); //! ``` //! -//! Based on [@babel/helper](https://github.com/babel/babel/tree/main/packages/babel-helpers). +//! Based on [@babel/helper](https://github.com/babel/babel/tree/v7.26.2/packages/babel-helpers). //! //! ## Implementation //! diff --git a/crates/oxc_transformer/src/common/module_imports.rs b/crates/oxc_transformer/src/common/module_imports.rs index 94c4c2a1830b21..87a64a311d548e 100644 --- a/crates/oxc_transformer/src/common/module_imports.rs +++ b/crates/oxc_transformer/src/common/module_imports.rs @@ -30,7 +30,7 @@ //! > NOTE: Using `import` or `require` is determined by [`TransformCtx::source_type`]. //! //! Based on `@babel/helper-module-imports` -//! +//! use std::cell::RefCell; diff --git a/crates/oxc_transformer/src/es2015/arrow_functions.rs b/crates/oxc_transformer/src/es2015/arrow_functions.rs index a0779dd52a5e83..a6ae357f2c2b02 100644 --- a/crates/oxc_transformer/src/es2015/arrow_functions.rs +++ b/crates/oxc_transformer/src/es2015/arrow_functions.rs @@ -122,7 +122,7 @@ //! //! ## References: //! -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Arrow function specification: use serde::Deserialize; diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 716ade8cf25dd4..38254c188783dd 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -27,8 +27,8 @@ //! ## References: //! //! * Babel plugin implementation: -//! -//! +//! +//! //! * Exponentiation operator TC39 proposal: //! * Exponentiation operator specification: diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index c7107ee576cc75..9e8729f59fe8a3 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -48,7 +48,7 @@ //! //! Reference: //! * Babel docs: -//! * Babel implementation: +//! * Babel implementation: //! * Async / Await TC39 proposal: use std::mem; diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs index 1b0d5c93291158..45a2847a772747 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs @@ -61,7 +61,7 @@ //! //! Reference: //! * Babel docs: -//! * Babel implementation: +//! * Babel implementation: //! * Async Iteration TC39 proposal: mod for_await; diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index 0daaf88ca3aa2c..39963df9871864 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -23,7 +23,7 @@ //! Implementation based on [@babel/plugin-transform-object-rest-spread](https://babeljs.io/docs/babel-plugin-transform-object-rest-spread). //! //! ## References: -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Object rest/spread TC39 proposal: use serde::Deserialize; diff --git a/crates/oxc_transformer/src/es2019/optional_catch_binding.rs b/crates/oxc_transformer/src/es2019/optional_catch_binding.rs index 5d9d98eda40cf5..304ced8b7fadbb 100644 --- a/crates/oxc_transformer/src/es2019/optional_catch_binding.rs +++ b/crates/oxc_transformer/src/es2019/optional_catch_binding.rs @@ -30,7 +30,7 @@ //! Implementation based on [@babel/plugin-transform-optional-catch-binding](https://babel.dev/docs/babel-plugin-transform-optional-catch-binding). //! //! ## References: -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Optional catch binding TC39 proposal: use oxc_ast::ast::*; diff --git a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs index 50dc3b59499418..ecefb0fe8def0b 100644 --- a/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs +++ b/crates/oxc_transformer/src/es2020/nullish_coalescing_operator.rs @@ -25,7 +25,7 @@ //! Implementation based on [@babel/plugin-transform-nullish-coalescing-operator](https://babeljs.io/docs/babel-plugin-transform-nullish-coalescing-operator). //! //! ## References: -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Nullish coalescing TC39 proposal: use oxc_allocator::Box as ArenaBox; diff --git a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs index e2e8fbf4f491de..a06d2bb8dd4522 100644 --- a/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs +++ b/crates/oxc_transformer/src/es2021/logical_assignment_operators.rs @@ -51,7 +51,7 @@ //! Implementation based on [@babel/plugin-transform-logical-assignment-operators](https://babel.dev/docs/babel-plugin-transform-logical-assignment-operators). //! //! ## References: -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Logical Assignment TC39 proposal: use oxc_allocator::CloneIn; diff --git a/crates/oxc_transformer/src/es2022/class_properties.rs b/crates/oxc_transformer/src/es2022/class_properties.rs index 5087d26aa86c34..becd2424c9f246 100644 --- a/crates/oxc_transformer/src/es2022/class_properties.rs +++ b/crates/oxc_transformer/src/es2022/class_properties.rs @@ -57,9 +57,9 @@ //! //! ## References: //! * Babel plugin implementation: -//! * -//! * -//! * +//! * +//! * +//! * //! * Class properties TC39 proposal: use serde::Deserialize; diff --git a/crates/oxc_transformer/src/es2022/class_static_block.rs b/crates/oxc_transformer/src/es2022/class_static_block.rs index f19ec629652da2..c1aaf5c26855c6 100644 --- a/crates/oxc_transformer/src/es2022/class_static_block.rs +++ b/crates/oxc_transformer/src/es2022/class_static_block.rs @@ -36,7 +36,7 @@ //! Implementation based on [@babel/plugin-transform-class-static-block](https://babel.dev/docs/babel-plugin-transform-class-static-block). //! //! ## References: -//! * Babel plugin implementation: +//! * Babel plugin implementation: //! * Class static initialization blocks TC39 proposal: use itoa::Buffer as ItoaBuffer; diff --git a/crates/oxc_transformer/src/jsx/display_name.rs b/crates/oxc_transformer/src/jsx/display_name.rs index f37b0d1154e7a2..05b9c92c0374ed 100644 --- a/crates/oxc_transformer/src/jsx/display_name.rs +++ b/crates/oxc_transformer/src/jsx/display_name.rs @@ -43,7 +43,7 @@ //! //! ## References: //! -//! * Babel plugin implementation: +//! * Babel plugin implementation: use oxc_ast::ast::*; use oxc_span::{Atom, SPAN}; diff --git a/crates/oxc_transformer/src/jsx/jsx_impl.rs b/crates/oxc_transformer/src/jsx/jsx_impl.rs index db972b6b511a47..8d58728d9be144 100644 --- a/crates/oxc_transformer/src/jsx/jsx_impl.rs +++ b/crates/oxc_transformer/src/jsx/jsx_impl.rs @@ -86,7 +86,7 @@ //! //! ## References: //! -//! * Babel plugin implementation: +//! * Babel plugin implementation: use oxc_allocator::Vec as ArenaVec; use oxc_ast::{ast::*, AstBuilder, NONE}; diff --git a/crates/oxc_transformer/src/jsx/jsx_self.rs b/crates/oxc_transformer/src/jsx/jsx_self.rs index 8c90fdfd91dc93..940f84fc35c6e0 100644 --- a/crates/oxc_transformer/src/jsx/jsx_self.rs +++ b/crates/oxc_transformer/src/jsx/jsx_self.rs @@ -26,7 +26,7 @@ //! //! ## References: //! -//! * Babel plugin implementation: +//! * Babel plugin implementation: use oxc_ast::ast::*; use oxc_diagnostics::OxcDiagnostic; diff --git a/crates/oxc_transformer/src/jsx/jsx_source.rs b/crates/oxc_transformer/src/jsx/jsx_source.rs index 950473b35a3e71..232cc4fba99ee6 100644 --- a/crates/oxc_transformer/src/jsx/jsx_source.rs +++ b/crates/oxc_transformer/src/jsx/jsx_source.rs @@ -31,7 +31,7 @@ //! //! ## References: //! -//! * Babel plugin implementation: +//! * Babel plugin implementation: use ropey::Rope; diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index 0598d5150719e5..a7145f0d06660f 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -99,7 +99,7 @@ impl<'a> RefreshIdentifierResolver<'a> { /// References: /// /// * -/// * +/// * pub struct ReactRefresh<'a, 'ctx> { refresh_reg: RefreshIdentifierResolver<'a>, refresh_sig: RefreshIdentifierResolver<'a>, diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index dd321309b39e68..474564f4339b0c 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -3,7 +3,7 @@ //! References: //! * //! * -//! * +//! * use std::path::Path; diff --git a/crates/oxc_transformer/tests/integrations/plugins/inject_global_variables.rs b/crates/oxc_transformer/tests/integrations/plugins/inject_global_variables.rs index 26ee7e9b6b0eb6..03835d70ed99ae 100644 --- a/crates/oxc_transformer/tests/integrations/plugins/inject_global_variables.rs +++ b/crates/oxc_transformer/tests/integrations/plugins/inject_global_variables.rs @@ -1,6 +1,6 @@ //! References //! -//! * +//! * use oxc_allocator::Allocator; use oxc_codegen::{CodeGenerator, CodegenOptions}; diff --git a/napi/parser/index.d.ts b/napi/parser/index.d.ts index d2bc98de30bf34..a36ba4bec60909 100644 --- a/napi/parser/index.d.ts +++ b/napi/parser/index.d.ts @@ -102,7 +102,7 @@ export interface ParseResult { /** * Babel Parser Options * - * + * */ export interface ParserOptions { sourceType?: 'script' | 'module' | 'unambiguous' | undefined diff --git a/napi/transform/index.d.ts b/napi/transform/index.d.ts index 4c76416ab66b9a..9fd1aca75d5cbc 100644 --- a/napi/transform/index.d.ts +++ b/napi/transform/index.d.ts @@ -127,7 +127,7 @@ export interface JsxOptions { /** * Enable React Fast Refresh . * - * Conforms to the implementation in {@link https://github.com/facebook/react/tree/main/packages/react-refresh} + * Conforms to the implementation in {@link https://github.com/facebook/react/tree/v18.3.1/packages/react-refresh} * * @default false */ diff --git a/npm/oxc-parser/scripts/generate-packages.mjs b/npm/oxc-parser/scripts/generate-packages.mjs index 624450780c3096..30a064712a322e 100644 --- a/npm/oxc-parser/scripts/generate-packages.mjs +++ b/npm/oxc-parser/scripts/generate-packages.mjs @@ -1,4 +1,4 @@ -// Code copied from [Rome](https://github.com/rome/tools/blob/main/npm/rome/scripts/generate-packages.mjs) +// Code copied from [Rome](https://github.com/rome/tools/blob/lsp/v0.28.0/npm/rome/scripts/generate-packages.mjs) import * as fs from 'node:fs'; import { resolve } from 'node:path'; diff --git a/npm/oxc-transform/scripts/generate-packages.mjs b/npm/oxc-transform/scripts/generate-packages.mjs index 555ebc0492ebe2..5205fef3ca81f3 100644 --- a/npm/oxc-transform/scripts/generate-packages.mjs +++ b/npm/oxc-transform/scripts/generate-packages.mjs @@ -1,4 +1,4 @@ -// Code copied from [Rome](https://github.com/rome/tools/blob/main/npm/rome/scripts/generate-packages.mjs) +// Code copied from [Rome](https://github.com/rome/tools/blob/lsp/v0.28.0/npm/rome/scripts/generate-packages.mjs) import * as fs from 'node:fs'; import { resolve } from 'node:path'; diff --git a/npm/oxlint/scripts/generate-packages.mjs b/npm/oxlint/scripts/generate-packages.mjs index 7768b560ff4583..e1c74af6feec95 100644 --- a/npm/oxlint/scripts/generate-packages.mjs +++ b/npm/oxlint/scripts/generate-packages.mjs @@ -1,4 +1,4 @@ -// Code copied from [Rome](https://github.com/rome/tools/blob/main/npm/rome/scripts/generate-packages.mjs) +// Code copied from [Rome](https://github.com/rome/tools/blob/lsp/v0.28.0/npm/rome/scripts/generate-packages.mjs) import * as fs from 'node:fs'; import { resolve } from 'node:path'; diff --git a/tasks/ast_tools/src/generators/visit.rs b/tasks/ast_tools/src/generators/visit.rs index a3df85f3a0e596..97b64535573417 100644 --- a/tasks/ast_tools/src/generators/visit.rs +++ b/tasks/ast_tools/src/generators/visit.rs @@ -74,7 +74,7 @@ fn generate_visit(is_mut: bool, schema: &Schema) -> TokenStream { //! //! See: //! * [visitor pattern](https://rust-unofficial.github.io/patterns/patterns/behavioural/visitor.html) - //! * [rustc visitor](https://github.com/rust-lang/rust/blob/master/compiler/rustc_ast/src/visit.rs) + //! * [rustc visitor](https://github.com/rust-lang/rust/blob/1.82.0/compiler/rustc_ast/src/visit.rs) //!@@line_break #![allow( diff --git a/tasks/common/src/test_file.rs b/tasks/common/src/test_file.rs index 410c8e9db14228..ec6b1fc69cc2a1 100644 --- a/tasks/common/src/test_file.rs +++ b/tasks/common/src/test_file.rs @@ -19,7 +19,7 @@ impl TestFiles { } } - /// These are kept in sync with + /// These are kept in sync with /// for checking against minification size in `tasks/minsize/minsize.snap`. pub fn minifier() -> Self { Self { diff --git a/tasks/compat_data/README.md b/tasks/compat_data/README.md index d7c9bd9f64aaef..2aeb38fd63345e 100644 --- a/tasks/compat_data/README.md +++ b/tasks/compat_data/README.md @@ -2,7 +2,7 @@ Get engine compatibility Data from https://github.com/compat-table/compat-table/ -Code extracted from https://github.com/babel/babel/tree/main/packages/babel-compat-data +Code extracted from https://github.com/babel/babel/tree/v7.26.2/packages/babel-compat-data ## Adding a new feature diff --git a/tasks/compat_data/build.js b/tasks/compat_data/build.js index 0142ab262057f1..909355d6069a8c 100644 --- a/tasks/compat_data/build.js +++ b/tasks/compat_data/build.js @@ -1,5 +1,5 @@ -// https://github.com/babel/babel/blob/main/packages/babel-compat-data/scripts/build-data.js -// https://github.com/babel/babel/blob/main/packages/babel-compat-data/scripts/utils-build-data.js +// https://github.com/babel/babel/blob/v7.26.2/packages/babel-compat-data/scripts/build-data.js +// https://github.com/babel/babel/blob/v7.26.2/packages/babel-compat-data/scripts/utils-build-data.js const fs = require('node:fs'); const envs = require('./compat-table/environments'); diff --git a/tasks/compat_data/chromium-to-electron.js b/tasks/compat_data/chromium-to-electron.js index ed01aeda05d1bf..b0bc83b52b137d 100644 --- a/tasks/compat_data/chromium-to-electron.js +++ b/tasks/compat_data/chromium-to-electron.js @@ -1,4 +1,4 @@ -// https://github.com/babel/babel/blob/main/packages/babel-compat-data/scripts/chromium-to-electron.js +// https://github.com/babel/babel/blob/v7.26.2/packages/babel-compat-data/scripts/chromium-to-electron.js const chromiumVersions = require('./chromium-versions'); const chromiumVersionList = Object.keys(chromiumVersions); diff --git a/tasks/compat_data/chromium-versions.js b/tasks/compat_data/chromium-versions.js index c1e1ea0159e2dc..57c33200250dcc 100644 --- a/tasks/compat_data/chromium-versions.js +++ b/tasks/compat_data/chromium-versions.js @@ -1,4 +1,4 @@ -// https://github.com/Kilian/electron-to-chromium/blob/master/chromium-versions.js +// https://github.com/Kilian/electron-to-chromium/blob/v1.5.60/chromium-versions.js module.exports = { '39': '0.20', diff --git a/tasks/compat_data/es-features.js b/tasks/compat_data/es-features.js index 7e5414a62a271e..fd31390efc8ae0 100644 --- a/tasks/compat_data/es-features.js +++ b/tasks/compat_data/es-features.js @@ -1,5 +1,5 @@ -// https://github.com/babel/babel/blob/main/packages/babel-compat-data/scripts/data/plugin-features.js -// https://github.com/evanw/esbuild/blob/main/compat-table/src/index.ts +// https://github.com/babel/babel/blob/v7.26.2/packages/babel-compat-data/scripts/data/plugin-features.js +// https://github.com/evanw/esbuild/blob/v0.24.0/compat-table/src/index.ts const f = (es) => (item) => { item.es = es; diff --git a/tasks/coverage/misc/fail/oxc-2394.ts b/tasks/coverage/misc/fail/oxc-2394.ts index 5dad81f5f032ad..2d4f916044e6ec 100644 --- a/tasks/coverage/misc/fail/oxc-2394.ts +++ b/tasks/coverage/misc/fail/oxc-2394.ts @@ -1,4 +1,4 @@ -// copy from https://github.com/microsoft/TypeScript/blob/main/tests/cases/conformance/node/nodeModulesImportAttributesTypeModeDeclarationEmitErrors.ts#L72 +// copy from https://github.com/microsoft/TypeScript/blob/v5.6.3/tests/cases/conformance/node/nodeModulesImportAttributesTypeModeDeclarationEmitErrors.ts#L72 // @filename: /node_modules/pkg/import.d.ts export interface ImportInterface {} diff --git a/tasks/coverage/src/runtime/runtime.js b/tasks/coverage/src/runtime/runtime.js index 48622535147be1..7d371345b25a9e 100644 --- a/tasks/coverage/src/runtime/runtime.js +++ b/tasks/coverage/src/runtime/runtime.js @@ -1,4 +1,4 @@ -// https://github.com/evanw/esbuild/blob/main/scripts/test262.js +// https://github.com/evanw/esbuild/blob/v0.24.0/scripts/test262.js // import fs from 'node:fs'; import { createServer } from 'node:http'; diff --git a/tasks/coverage/src/suite.rs b/tasks/coverage/src/suite.rs index e14da73823565d..1887bdd466cfe6 100644 --- a/tasks/coverage/src/suite.rs +++ b/tasks/coverage/src/suite.rs @@ -286,7 +286,7 @@ pub trait Case: Sized + Sync + Send + UnwindSafe { /// Mark strict mode as always strict /// - /// See + /// See fn always_strict(&self) -> bool { false } diff --git a/tasks/coverage/src/test262/mod.rs b/tasks/coverage/src/test262/mod.rs index b9224db648b2a0..46bca3b1fda7d5 100644 --- a/tasks/coverage/src/test262/mod.rs +++ b/tasks/coverage/src/test262/mod.rs @@ -116,7 +116,7 @@ impl Case for Test262Case { // each test must be executed twice: once in ECMAScript's non-strict mode, and again in ECMAScript's strict mode. // To run in strict mode, the test contents must be modified prior to execution-- // a "use strict" directive must be inserted as the initial character sequence of the file - // https://github.com/tc39/test262/blob/main/INTERPRETING.md#strict-mode + // https://github.com/tc39/test262/blob/05c45a4c430ab6fee3e0c7f0d47d8a30d8876a6d/INTERPRETING.md#strict-mode fn run(&mut self) { let flags = &self.meta.flags; let source_type = SourceType::cjs(); diff --git a/tasks/coverage/src/typescript/transpile_runner.rs b/tasks/coverage/src/typescript/transpile_runner.rs index 1f292cb5897864..30118f019dc79a 100644 --- a/tasks/coverage/src/typescript/transpile_runner.rs +++ b/tasks/coverage/src/typescript/transpile_runner.rs @@ -1,4 +1,4 @@ -//! +//! use std::path::{Path, PathBuf}; diff --git a/tasks/lint_rules/src/eslint-rules.cjs b/tasks/lint_rules/src/eslint-rules.cjs index 25030def8d4969..f34d57a5f0c4ab 100644 --- a/tasks/lint_rules/src/eslint-rules.cjs +++ b/tasks/lint_rules/src/eslint-rules.cjs @@ -9,59 +9,59 @@ const { Linter } = require('eslint'); // - rule.meta.docs.recommended // Some plugins have the recommended flag in rule itself, but some plugins have it in config. -// https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/src/index.ts +// https://github.com/typescript-eslint/typescript-eslint/blob/v8.9.0/packages/eslint-plugin/src/index.ts const { rules: pluginTypeScriptAllRules, configs: pluginTypeScriptConfigs, } = require('@typescript-eslint/eslint-plugin'); -// https://github.com/eslint-community/eslint-plugin-n/blob/master/lib/index.js +// https://github.com/eslint-community/eslint-plugin-n/blob/v17.13.2/lib/index.js const { rules: pluginNAllRules } = require('eslint-plugin-n'); -// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/index.js +// https://github.com/sindresorhus/eslint-plugin-unicorn/blob/v56.0.0/index.js const { rules: pluginUnicornAllRules, configs: pluginUnicornConfigs, } = require('eslint-plugin-unicorn'); -// https://github.com/gajus/eslint-plugin-jsdoc/blob/main/src/index.js +// https://github.com/gajus/eslint-plugin-jsdoc/blob/v50.5.0/src/index.js const { // @ts-expect-error: Module has no exported member rules: pluginJSDocAllRules, // @ts-expect-error: Module has no exported member configs: pluginJSDocConfigs, } = require('eslint-plugin-jsdoc'); -// https://github.com/import-js/eslint-plugin-import/blob/main/src/index.js +// https://github.com/import-js/eslint-plugin-import/blob/v2.29.1/src/index.js const { rules: pluginImportAllRules, configs: pluginImportConfigs, } = require('eslint-plugin-import'); -// https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/src/index.js +// https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/v6.9.0/src/index.js const { rules: pluginJSXA11yAllRules, configs: pluginJSXA11yConfigs, } = require('eslint-plugin-jsx-a11y'); -// https://github.com/jest-community/eslint-plugin-jest/blob/main/src/index.ts +// https://github.com/jest-community/eslint-plugin-jest/blob/v28.9.0/src/index.ts const { rules: pluginJestAllRules, configs: pluginJestConfigs, } = require('eslint-plugin-jest'); -// https://github.com/jsx-eslint/eslint-plugin-react/blob/master/index.js +// https://github.com/jsx-eslint/eslint-plugin-react/blob/v7.37.2/index.js const { rules: pluginReactAllRules } = require('eslint-plugin-react'); -// https://github.com/facebook/react/blob/main/packages/eslint-plugin-react-hooks/src/index.js +// https://github.com/facebook/react/blob/v18.3.1/packages/eslint-plugin-react-hooks/src/index.js const { rules: pluginReactHooksAllRules, } = require('eslint-plugin-react-hooks'); -// https://github.com/cvazac/eslint-plugin-react-perf/blob/master/index.js +// https://github.com/cvazac/eslint-plugin-react-perf/blob/9bfa930661a23218f5460ebd39d35d76ccdb5724/index.js const { rules: pluginReactPerfAllRules, configs: pluginReactPerfConfigs, } = require('eslint-plugin-react-perf'); // https://github.com/vercel/next.js/blob/canary/packages/eslint-plugin-next/src/index.ts const { rules: pluginNextAllRules } = require('@next/eslint-plugin-next'); -// https://github.com/eslint-community/eslint-plugin-promise/blob/main/index.js +// https://github.com/eslint-community/eslint-plugin-promise/blob/v7.1.0/index.js const { rules: pluginPromiseRules, configs: pluginPromiseConfigs, } = require('eslint-plugin-promise'); -// https://github.com/veritem/eslint-plugin-vitest/blob/main/src/index.ts +// https://github.com/veritem/eslint-plugin-vitest/blob/v1.1.9/src/index.ts const { rules: pluginVitestRules, configs: pluginVitestConfigs, diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/react-refresh/README.md b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/react-refresh/README.md index 45183164a06002..8603a42506e20b 100644 --- a/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/react-refresh/README.md +++ b/tasks/transform_conformance/tests/babel-plugin-transform-react-jsx/test/fixtures/refresh/react-refresh/README.md @@ -1,3 +1,3 @@ -The tests of this directory are copied from the (react-refresh)[https://github.com/facebook/react/blob/main/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js], and did some style, import order, and other minor changes to made them work with our transformer. +The tests of this directory are copied from the (react-refresh)[https://github.com/facebook/react/blob/v18.3.1/packages/react-refresh/src/__tests__/ReactFreshBabelPlugin-test.js], and did some style, import order, and other minor changes to made them work with our transformer. NOTE: This directory only add tests copied from the upstream, so that we can distinguish the source of the test \ No newline at end of file From 28d37e478dd820f77acc1c70b2fcd6ab57b01a86 Mon Sep 17 00:00:00 2001 From: dalaoshu Date: Sun, 17 Nov 2024 00:30:56 +0800 Subject: [PATCH 013/121] chore(justfile): add `pnpm install` to init (#7297) Recently, due to some issues, I had to re-clone the oxc project multiple times. After running `just init`, I always had to run `pnpm install` separately. We could include `pnpm install` to init command to streamline the process. In addition, I propose to include `cargo-binstall` in the init command. I'm not sure if we should include the `submodules` command in the init command, as it is generally unnecessary for most users unless they are working on specific projects like the minifier. --- justfile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/justfile b/justfile index 9419c85c696c2c..fe94849a8d3976 100755 --- a/justfile +++ b/justfile @@ -16,7 +16,10 @@ alias new-typescript-rule := new-ts-rule # or install via `cargo install cargo-binstall` # Initialize the project by installing all the necessary tools. init: + # Rust related init cargo binstall watchexec-cli cargo-insta typos-cli cargo-shear dprint -y + # Node.js related init + pnpm install # When ready, run the same CI commands ready: From d445e0f6121fed53a772fa9aec6ef6b96528bd53 Mon Sep 17 00:00:00 2001 From: Ryan Walker Date: Sat, 16 Nov 2024 12:07:52 -0800 Subject: [PATCH 014/121] feat(linter): implement `unicorn/consistent-existence-index-check` (#7262) [unicorn/consistent-existence-index-check](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/consistent-existence-index-check.md) for #684 --------- Co-authored-by: Cam McHenry --- crates/oxc_linter/src/rules.rs | 2 + .../consistent_existence_index_check.rs | 676 ++++++++++++++++++ .../consistent_existence_index_check.snap | 142 ++++ 3 files changed, 820 insertions(+) create mode 100644 crates/oxc_linter/src/rules/unicorn/consistent_existence_index_check.rs create mode 100644 crates/oxc_linter/src/snapshots/consistent_existence_index_check.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 8714025070a8a2..381bce640d212d 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -282,6 +282,7 @@ mod react_perf { mod unicorn { pub mod catch_error_name; pub mod consistent_empty_array_spread; + pub mod consistent_existence_index_check; pub mod consistent_function_scoping; pub mod empty_brace_spaces; pub mod error_message; @@ -869,6 +870,7 @@ oxc_macros::declare_all_lint_rules! { typescript::triple_slash_reference, unicorn::catch_error_name, unicorn::consistent_empty_array_spread, + unicorn::consistent_existence_index_check, unicorn::consistent_function_scoping, unicorn::empty_brace_spaces, unicorn::error_message, diff --git a/crates/oxc_linter/src/rules/unicorn/consistent_existence_index_check.rs b/crates/oxc_linter/src/rules/unicorn/consistent_existence_index_check.rs new file mode 100644 index 00000000000000..f2bb4dbbde6da3 --- /dev/null +++ b/crates/oxc_linter/src/rules/unicorn/consistent_existence_index_check.rs @@ -0,0 +1,676 @@ +use oxc_ast::{ + ast::{BinaryOperator, Expression, UnaryOperator, VariableDeclarationKind}, + AstKind, +}; + +use oxc_diagnostics::OxcDiagnostic; +use oxc_macros::declare_oxc_lint; +use oxc_semantic::AstNode; +use oxc_span::{GetSpan, Span}; + +use crate::{context::LintContext, rule::Rule}; + +#[derive(Debug, Default, Clone)] +pub struct ConsistentExistenceIndexCheck; + +fn consistent_existence_index_check_diagnostic( + replacement: &GetReplacementOutput, + span: Span, +) -> OxcDiagnostic { + let existence_or_non_existence = + if replacement.replacement_value == "-1" { "non-existence" } else { "existence" }; + + let label = format!( + "Prefer `{replacement_operator} {replacement_value}` over `{original_operator} {original_value}` to check {existenceOrNonExistence}.", + replacement_operator = replacement.replacement_operator, + replacement_value = replacement.replacement_value, + original_operator = replacement.original_operator, + original_value = replacement.original_value, + existenceOrNonExistence = existence_or_non_existence, + ); + + OxcDiagnostic::warn(label).with_label(span) +} + +declare_oxc_lint!( + /// ### What it does + /// + /// Enforce consistent style for element existence checks with `indexOf()`, `lastIndexOf()`, `findIndex()`, and `findLastIndex()` + /// + /// ### Why is this bad? + /// + /// This rule is only meant to enforce a specific style and make comparisons more clear. + /// + /// ### Examples + /// + /// Examples of **incorrect** code for this rule: + /// + /// ```javascript + /// const index = foo.indexOf('bar'); + /// if (index < 0) {} + /// ``` + /// + /// ``` javascript + /// const index = foo.indexOf('bar'); + /// if (index >= 0) {} + /// ``` + /// + /// Examples of **correct** code for this rule: + /// + /// ```javascript + /// const index = foo.indexOf('bar'); + /// if (index === -1) {} + /// ``` + /// + /// ``` javascript + /// const index = foo.indexOf('bar'); + /// if (index !== -1) {} + /// ``` + ConsistentExistenceIndexCheck, + style, + fix, +); + +const METHOD_NAMES: [&str; 4] = ["indexOf", "lastIndexOf", "findIndex", "findLastIndex"]; + +impl Rule for ConsistentExistenceIndexCheck { + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + let AstKind::BinaryExpression(binary_expression) = node.kind() else { + return; + }; + + let left = binary_expression.left.get_inner_expression(); + let right = binary_expression.right.get_inner_expression(); + let operator = binary_expression.operator; + + let Expression::Identifier(identifier) = left else { + return; + }; + + let Some(reference_id) = identifier.reference_id.get() else { + return; + }; + + let Some(reference_symbol_id) = ctx.symbols().get_reference(reference_id).symbol_id() + else { + return; + }; + + let declaration = ctx.symbols().get_declaration(reference_symbol_id); + let node = ctx.nodes().get_node(declaration); + + if let AstKind::VariableDeclarator(variables_declarator) = node.kind() { + if variables_declarator.kind != VariableDeclarationKind::Const { + return; + } + + let Some(Expression::CallExpression(call)) = &variables_declarator.init else { + return; + }; + + if !call.callee.is_member_expression() { + return; + } + + let Some(callee_name) = call.callee_name() else { + return; + }; + + if !METHOD_NAMES.contains(&callee_name) { + return; + } + + let replacement = get_replacement(right, operator); + + let Some(replacement) = &replacement else { + return; + }; + + ctx.diagnostic_with_fix( + consistent_existence_index_check_diagnostic(replacement, binary_expression.span), + |fixer| { + let operator_start = binary_expression.left.span().end; + let operator_end = binary_expression.right.span().start; + let operator_span = Span::new(operator_start, operator_end); + let operator_source = ctx.source_range(operator_span); + + let operator_matches = + operator_source.match_indices(replacement.original_operator); + let mut operator_replacement_text = operator_source.to_string(); + + for (index, text) in operator_matches { + let comments = ctx.semantic().comments_range(operator_start..operator_end); + + let start = operator_start + u32::try_from(index).unwrap_or(0); + let length = u32::try_from(text.len()).unwrap_or(0); + let span = Span::sized(start, length); + + let mut is_in_comment = false; + + for comment in comments { + if comment.span.contains_inclusive(span) { + is_in_comment = true; + break; + } + } + + if !is_in_comment { + let head = &operator_source[..index]; + let tail = &operator_source[index + text.len()..]; + + operator_replacement_text = + format!("{}{}{}", head, replacement.replacement_operator, tail); + } + } + + let fixer = fixer.for_multifix(); + let mut rule_fixes = fixer.new_fix_with_capacity(2); + + rule_fixes.push(fixer.replace(operator_span, operator_replacement_text)); + rule_fixes.push(fixer.replace(right.span(), replacement.replacement_value)); + + rule_fixes + }, + ); + }; + } +} + +#[derive(Debug, Clone)] +struct GetReplacementOutput { + pub replacement_operator: &'static str, + pub replacement_value: &'static str, + pub original_operator: &'static str, + pub original_value: &'static str, +} + +fn get_replacement(right: &Expression, operator: BinaryOperator) -> Option { + match operator { + BinaryOperator::LessThan => { + if right.is_number_0() { + return Some(GetReplacementOutput { + replacement_operator: "===", + replacement_value: "-1", + original_operator: "<", + original_value: "0", + }); + } + + None + } + BinaryOperator::GreaterThan => { + if is_negative_one(right.get_inner_expression()) { + return Some(GetReplacementOutput { + replacement_operator: "!==", + replacement_value: "-1", + original_operator: ">", + original_value: "-1", + }); + } + + None + } + BinaryOperator::GreaterEqualThan => { + if right.is_number_0() { + return Some(GetReplacementOutput { + replacement_operator: "!==", + replacement_value: "-1", + original_operator: ">=", + original_value: "0", + }); + } + + None + } + _ => None, + } +} + +fn is_negative_one(expression: &Expression) -> bool { + if let Expression::UnaryExpression(unary_expression) = expression { + if let UnaryOperator::UnaryNegation = unary_expression.operator { + if let Expression::NumericLiteral(value) = + &unary_expression.argument.get_inner_expression() + { + return value.raw == "1"; + } + } + } + + false +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass: Vec<&str> = vec![ + // Skip checking if indexOf() method is not a method call from a object + r" + const index = indexOf('bar'); + if (index > -1) {} + ", + r" + const index = foo.indexOf('bar'); + if (index === -1) {} + ", + r" + const index = foo.indexOf('bar'); + if (-1 === index) {} + ", + r" + const index = foo.indexOf('bar'); + if (index !== -1) {} + ", + r" + const index = foo.indexOf('bar'); + if (-1 !== index) {} + ", + // // Variable index is not from indexOf + r" + const index = 0; + if (index < 0) {} + ", + // If index is not declared via VariableDeclarator, it will not be check here. + r" + function foo (index) { + if (index < 0) {} + } + ", + // Since the variable is references from function parameter, it will not be checked here + r" + const index = foo.indexOf('bar'); + function foo (index) { + if (index < 0) {} + } + ", + // To prevent false positives, it will not check if the index is not declared via const + r" + let index = foo.indexOf('bar'); + + index < 0 + ", + // To prevent false positives, it will not check if the index is not declared via const + r" + var index = foo.indexOf('bar'); + index < 0 + ", + // To prevent false positives, it will not check if the index is not declared via const + r" + let index; + + // do stuff + + index = arr.findLastIndex(element => element > 10); + index < 0; + ", + r"const indexOf = 'indexOf'; const index = foo[indexOf](foo); index < 0;", + r"const index = foo.indexOf?.(foo); index < 0;", + r"const index = foo?.indexOf(foo); index < 0;", + ]; + + let fail = vec![ + r"const index = foo.indexOf('bar'); if (index < 0) {}", + r"const index = foo.lastIndexOf('bar'); if (index < 0) {}", + r"const index = foo.findIndex('bar'); if (index < 0) {}", + r"const index = foo.findLastIndex('bar'); if (index < 0) {}", + r"const index = foo.indexOf('bar'); if (index >= 0) {}", + r"const index = foo.lastIndexOf('bar'); if (index >= 0) {}", + r"const index = foo.findIndex('bar'); if (index >= 0) {}", + r"const index = foo.findLastIndex('bar'); if (index >= 0) {}", + r"const index = foo.indexOf('bar'); if (index > -1) {}", + r"const index = foo.lastIndexOf('bar'); if (index > -1) {}", + r"const index = foo.findIndex('bar'); if (index > -1) {}", + r"const index = foo.findLastIndex('bar'); if (index > -1) {}", + r" + const index = foo.indexOf(bar); + + function foo () { + if (index < 0) {} + } + ", + r" + const index1 = foo.indexOf('1'), + index2 = foo.indexOf('2'); + index1 < 0; + index2 >= 0; + ", + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + < + /* comment 5 */ + (( + /* comment 6 */ + 0 + /* comment 7 */ + )) + /* comment 8 */ + )); + ", + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + > + (( + /* comment 5 */ + - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ )) + /* comment 9 */ + )) + )); + ", + r"const index = _.indexOf([1, 2, 1, 2], 2); index < 0;", + ]; + + let fix = vec![ + ( + r"const index = foo.indexOf('bar'); if (index < 0) {}", + r"const index = foo.indexOf('bar'); if (index === -1) {}", + None, + ), + ( + r"const index = foo.lastIndexOf('bar'); if (index < 0) {}", + r"const index = foo.lastIndexOf('bar'); if (index === -1) {}", + None, + ), + ( + r"const index = foo.findIndex('bar'); if (index < 0) {}", + r"const index = foo.findIndex('bar'); if (index === -1) {}", + None, + ), + ( + r"const index = foo.findLastIndex('bar'); if (index < 0) {}", + r"const index = foo.findLastIndex('bar'); if (index === -1) {}", + None, + ), + ( + r"const index = foo.indexOf('bar'); if (index >= 0) {}", + r"const index = foo.indexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.lastIndexOf('bar'); if (index >= 0) {}", + r"const index = foo.lastIndexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findIndex('bar'); if (index >= 0) {}", + r"const index = foo.findIndex('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findLastIndex('bar'); if (index >= 0) {}", + r"const index = foo.findLastIndex('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.indexOf('bar'); if (index > -1) {}", + r"const index = foo.indexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.lastIndexOf('bar'); if (index > -1) {}", + r"const index = foo.lastIndexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findIndex('bar'); if (index > -1) {}", + r"const index = foo.findIndex('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findLastIndex('bar'); if (index > -1) {}", + r"const index = foo.findLastIndex('bar'); if (index !== -1) {}", + None, + ), + ( + r" + const index = foo.indexOf(bar); + + function foo () { + if (index < 0) {} + } + ", + r" + const index = foo.indexOf(bar); + + function foo () { + if (index === -1) {} + } + ", + None, + ), + ( + r" + const index1 = foo.indexOf('1'), + index2 = foo.indexOf('2'); + index1 < 0; + index2 >= 0; + ", + r" + const index1 = foo.indexOf('1'), + index2 = foo.indexOf('2'); + index1 === -1; + index2 !== -1; + ", + None, + ), + ( + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + < + /* comment 5 */ + (( + /* comment 6 */ + 0 + /* comment 7 */ + )) + /* comment 8 */ + )); + ", + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + === + /* comment 5 */ + (( + /* comment 6 */ + -1 + /* comment 7 */ + )) + /* comment 8 */ + )); + ", + None, + ), + ( + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + > + (( + /* comment 5 */ + - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ )) + /* comment 9 */ + )) + )); + ", + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 */ + !== + (( + /* comment 5 */ + -1 + /* comment 9 */ + )) + )); + ", + None, + ), + ( + r"const index = _.indexOf([1, 2, 1, 2], 2); index < 0;", + r"const index = _.indexOf([1, 2, 1, 2], 2); index === -1;", + None, + ), + ( + r"const i = foo.indexOf('bar'); if (i /* < */ < 0) {}", + r"const i = foo.indexOf('bar'); if (i /* < */ === -1) {}", + None, + ), + // make sure to not replace the wrong operator + ( + r" + const index = foo.indexOf('bar'); + if ( + index + /* >= */ + >= + 0 + ) {} + ", + r" + const index = foo.indexOf('bar'); + if ( + index + /* >= */ + !== + -1 + ) {} + ", + None, + ), + // make sure to not replace the wrong operator + ( + r" + const index = foo.indexOf('bar'); + if ( + index + /* >= */ + >= // >= + 0 + ) {} + ", + r" + const index = foo.indexOf('bar'); + if ( + index + /* >= */ + !== // >= + -1 + ) {} + ", + None, + ), + ( + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 < */ + < + /* comment 5 */ + (( + /* comment 6 */ + 0 + /* comment 7 */ + )) + /* comment 8 */ + )); + ", + r" + const index = foo.indexOf('1'); + (( + /* comment 1 */ + (( + /* comment 2 */ + index + /* comment 3 */ + )) + /* comment 4 < */ + === + /* comment 5 */ + (( + /* comment 6 */ + -1 + /* comment 7 */ + )) + /* comment 8 */ + )); + ", + None, + ), + ( + r"const index = foo.indexOf('bar'); if (index >= 0) {}", + r"const index = foo.indexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.lastIndexOf('bar'); if (index >= 0) {}", + r"const index = foo.lastIndexOf('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findIndex('bar'); if (index >= 0) {}", + r"const index = foo.findIndex('bar'); if (index !== -1) {}", + None, + ), + ( + r"const index = foo.findLastIndex('bar'); if (index >= 0) {}", + r"const index = foo.findLastIndex('bar'); if (index !== -1) {}", + None, + ), + ]; + + Tester::new(ConsistentExistenceIndexCheck::NAME, pass, fail) + .expect_fix(fix) + .test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/consistent_existence_index_check.snap b/crates/oxc_linter/src/snapshots/consistent_existence_index_check.snap new file mode 100644 index 00000000000000..4a8209eb75c2fa --- /dev/null +++ b/crates/oxc_linter/src/snapshots/consistent_existence_index_check.snap @@ -0,0 +1,142 @@ +--- +source: crates/oxc_linter/src/tester.rs +snapshot_kind: text +--- + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:39] + 1 β”‚ const index = foo.indexOf('bar'); if (index < 0) {} + Β· ───────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:43] + 1 β”‚ const index = foo.lastIndexOf('bar'); if (index < 0) {} + Β· ───────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:41] + 1 β”‚ const index = foo.findIndex('bar'); if (index < 0) {} + Β· ───────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:45] + 1 β”‚ const index = foo.findLastIndex('bar'); if (index < 0) {} + Β· ───────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `>= 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:39] + 1 β”‚ const index = foo.indexOf('bar'); if (index >= 0) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `>= 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:43] + 1 β”‚ const index = foo.lastIndexOf('bar'); if (index >= 0) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `>= 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:41] + 1 β”‚ const index = foo.findIndex('bar'); if (index >= 0) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `>= 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:45] + 1 β”‚ const index = foo.findLastIndex('bar'); if (index >= 0) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `> -1` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:39] + 1 β”‚ const index = foo.indexOf('bar'); if (index > -1) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `> -1` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:43] + 1 β”‚ const index = foo.lastIndexOf('bar'); if (index > -1) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `> -1` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:41] + 1 β”‚ const index = foo.findIndex('bar'); if (index > -1) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `> -1` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:45] + 1 β”‚ const index = foo.findLastIndex('bar'); if (index > -1) {} + Β· ────────── + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:5:15] + 4 β”‚ function foo () { + 5 β”‚ if (index < 0) {} + Β· ───────── + 6 β”‚ } + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:4:10] + 3 β”‚ index2 = foo.indexOf('2'); + 4 β”‚ index1 < 0; + Β· ────────── + 5 β”‚ index2 >= 0; + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `>= 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:5:10] + 4 β”‚ index1 < 0; + 5 β”‚ index2 >= 0; + Β· ─────────── + 6 β”‚ + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:5:17] + 4 β”‚ /* comment 1 */ + 5 β”‚ ╭─▢ (( + 6 β”‚ β”‚ /* comment 2 */ + 7 β”‚ β”‚ index + 8 β”‚ β”‚ /* comment 3 */ + 9 β”‚ β”‚ )) + 10 β”‚ β”‚ /* comment 4 */ + 11 β”‚ β”‚ < + 12 β”‚ β”‚ /* comment 5 */ + 13 β”‚ β”‚ (( + 14 β”‚ β”‚ /* comment 6 */ + 15 β”‚ β”‚ 0 + 16 β”‚ β”‚ /* comment 7 */ + 17 β”‚ ╰─▢ )) + 18 β”‚ /* comment 8 */ + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `!== -1` over `> -1` to check non-existence. + ╭─[consistent_existence_index_check.tsx:5:11] + 4 β”‚ /* comment 1 */ + 5 β”‚ ╭─▢ (( + 6 β”‚ β”‚ /* comment 2 */ + 7 β”‚ β”‚ index + 8 β”‚ β”‚ /* comment 3 */ + 9 β”‚ β”‚ )) + 10 β”‚ β”‚ /* comment 4 */ + 11 β”‚ β”‚ > + 12 β”‚ β”‚ (( + 13 β”‚ β”‚ /* comment 5 */ + 14 β”‚ β”‚ - /* comment 6 */ (( /* comment 7 */ 1 /* comment 8 */ )) + 15 β”‚ β”‚ /* comment 9 */ + 16 β”‚ ╰─▢ )) + 17 β”‚ )); + ╰──── + + ⚠ eslint-plugin-unicorn(consistent-existence-index-check): Prefer `=== -1` over `< 0` to check non-existence. + ╭─[consistent_existence_index_check.tsx:1:43] + 1 β”‚ const index = _.indexOf([1, 2, 1, 2], 2); index < 0; + Β· ───────── + ╰──── From 7d75130865fe193435cf555e7bec20f0802818d0 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:01:44 +0000 Subject: [PATCH 015/121] fix(transformer/async-to-generator): `arguments` isn't correct after transformation (#7234) Fix due to this plugin transforming the async method and async arrow function, it caused arguments no longer point the original function. For example: Before ```js class Cls { async method() { () => { console.log(arguments) } } } ``` After: ```js class Cls { method() { var _arguments = arguments; return babelHelpers.asyncToGenerator(function* () { () => { console.log(_arguments); }; })(); } } ``` In this way, the `_arguments` is its original function's arguments ### For performance regression It seems we need to check the IdentifierReference and BindingIdentifier if it's an `arguments`, that causes a significant regression, we may need a cheap way to do checking --- crates/oxc_semantic/src/reference.rs | 2 +- crates/oxc_semantic/src/scope.rs | 7 + crates/oxc_semantic/src/symbol.rs | 6 + .../src/common/arrow_function_converter.rs | 233 ++++++++++++++++-- crates/oxc_transformer/src/common/mod.rs | 16 ++ crates/oxc_transformer/src/lib.rs | 16 ++ .../snapshots/oxc.snap.md | 2 +- .../test/fixtures/arguments/assign/input.js | 4 + .../test/fixtures/arguments/assign/output.js | 9 + .../fixtures/arguments/async-method/input.js | 7 + .../fixtures/arguments/async-method/output.js | 10 + .../fixtures/arguments/nested-block/input.js | 7 + .../fixtures/arguments/nested-block/output.js | 12 + 13 files changed, 313 insertions(+), 18 deletions(-) create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/input.js create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/output.js create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/input.js create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/output.js create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/input.js create mode 100644 tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/output.js diff --git a/crates/oxc_semantic/src/reference.rs b/crates/oxc_semantic/src/reference.rs index 4bf1ecc4e63e1c..544e17d8887fda 100644 --- a/crates/oxc_semantic/src/reference.rs +++ b/crates/oxc_semantic/src/reference.rs @@ -81,7 +81,7 @@ impl Reference { } #[inline] - pub(crate) fn set_symbol_id(&mut self, symbol_id: SymbolId) { + pub fn set_symbol_id(&mut self, symbol_id: SymbolId) { self.symbol_id = Some(symbol_id); } diff --git a/crates/oxc_semantic/src/scope.rs b/crates/oxc_semantic/src/scope.rs index df526f5bfaed1a..612e6c93150fc0 100644 --- a/crates/oxc_semantic/src/scope.rs +++ b/crates/oxc_semantic/src/scope.rs @@ -351,6 +351,13 @@ impl ScopeTree { } } + /// Rename a binding to a new name. + pub fn rename_binding(&mut self, scope_id: ScopeId, old_name: &str, new_name: CompactStr) { + if let Some(symbol_id) = self.bindings[scope_id].shift_remove(old_name) { + self.bindings[scope_id].insert(new_name, symbol_id); + } + } + /// Reserve memory for an `additional` number of scopes. pub fn reserve(&mut self, additional: usize) { self.parent_ids.reserve(additional); diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index 3c220cbc6e5a08..1527997e53ccf7 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -102,6 +102,12 @@ impl SymbolTable { &self.names[symbol_id] } + /// Rename a symbol. + #[inline] + pub fn rename(&mut self, symbol_id: SymbolId, new_name: CompactStr) { + self.names[symbol_id] = new_name; + } + #[inline] pub fn set_name(&mut self, symbol_id: SymbolId, name: CompactStr) { self.names[symbol_id] = name; diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 9de158b3e68aff..acde13c691ff34 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -87,16 +87,18 @@ //! The Implementation based on //! +use rustc_hash::{FxHashMap, FxHashSet}; + use oxc_allocator::{Box as ArenaBox, String as ArenaString, Vec as ArenaVec}; use oxc_ast::{ast::*, AstBuilder, NONE}; use oxc_data_structures::stack::SparseStack; -use oxc_span::SPAN; +use oxc_semantic::{ReferenceFlags, SymbolId}; +use oxc_span::{CompactStr, SPAN}; use oxc_syntax::{ scope::{ScopeFlags, ScopeId}, symbol::SymbolFlags, }; use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx}; -use rustc_hash::FxHashMap; use crate::EnvOptions; @@ -125,6 +127,8 @@ struct SuperMethodInfo<'a> { pub struct ArrowFunctionConverter<'a> { mode: ArrowFunctionConverterMode, this_var_stack: SparseStack>, + arguments_var_stack: SparseStack>, + renamed_arguments_symbol_ids: FxHashSet, super_methods: Option, SuperMethodInfo<'a>>>, } @@ -137,8 +141,14 @@ impl<'a> ArrowFunctionConverter<'a> { } else { ArrowFunctionConverterMode::Disabled }; - // `SparseStack` is created with 1 empty entry, for `Program` - Self { mode, this_var_stack: SparseStack::new(), super_methods: None } + // `SparseStack`s are created with 1 empty entry, for `Program` + Self { + mode, + this_var_stack: SparseStack::new(), + arguments_var_stack: SparseStack::new(), + renamed_arguments_symbol_ids: FxHashSet::default(), + super_methods: None, + } } } @@ -153,14 +163,19 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { } let this_var = self.this_var_stack.take_last(); + let arguments_var = self.arguments_var_stack.take_last(); self.insert_variable_statement_at_the_top_of_statements( program.scope_id(), &mut program.body, this_var, + arguments_var, ctx, ); + debug_assert!(self.this_var_stack.len() == 1); debug_assert!(self.this_var_stack.last().is_none()); + debug_assert!(self.arguments_var_stack.len() == 1); + debug_assert!(self.arguments_var_stack.last().is_none()); } fn enter_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) { @@ -169,6 +184,7 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { } self.this_var_stack.push(None); + self.arguments_var_stack.push(None); if self.is_async_only() && func.r#async && Self::is_class_method_like_ancestor(ctx.parent()) { self.super_methods = Some(FxHashMap::default()); @@ -196,10 +212,12 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { return; }; let this_var = self.this_var_stack.pop(); + let arguments_var = self.arguments_var_stack.pop(); self.insert_variable_statement_at_the_top_of_statements( scope_id, &mut body.statements, this_var, + arguments_var, ctx, ); } @@ -222,6 +240,8 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { block.scope_id(), &mut block.body, this_var, + // `arguments` is not allowed to be used in static blocks + None, ctx, ); } @@ -301,6 +321,22 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { *expr = Self::transform_arrow_function_expression(arrow_function_expr, ctx); } } + + fn enter_identifier_reference( + &mut self, + ident: &mut IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.transform_identifier_reference_for_arguments(ident, ctx); + } + + fn enter_binding_identifier( + &mut self, + ident: &mut BindingIdentifier<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.transform_binding_identifier_for_arguments(ident, ctx); + } } impl<'a> ArrowFunctionConverter<'a> { @@ -787,28 +823,196 @@ impl<'a> ArrowFunctionConverter<'a> { ast.atom(name.into_bump_str()) } + /// Whether to transform the `arguments` identifier. + fn should_transform_arguments_identifier(&self, name: &str, ctx: &mut TraverseCtx<'a>) -> bool { + self.is_async_only() && name == "arguments" && Self::is_affected_arguments_identifier(ctx) + } + + /// Check if the `arguments` identifier is affected by the transformation. + fn is_affected_arguments_identifier(ctx: &mut TraverseCtx<'a>) -> bool { + let mut ancestors = ctx.ancestors().skip(1); + while let Some(ancestor) = ancestors.next() { + match ancestor { + Ancestor::ArrowFunctionExpressionParams(arrow) => { + if *arrow.r#async() { + return true; + } + } + Ancestor::ArrowFunctionExpressionBody(arrow) => { + if *arrow.r#async() { + return true; + } + } + Ancestor::FunctionBody(func) => { + return *func.r#async() + && Self::is_class_method_like_ancestor(ancestors.next().unwrap()); + } + _ => (), + } + } + + false + } + + /// Rename the `arguments` symbol to a new name. + fn rename_arguments_symbol(symbol_id: SymbolId, name: CompactStr, ctx: &mut TraverseCtx<'a>) { + let scope_id = ctx.symbols().get_scope_id(symbol_id); + ctx.symbols_mut().rename(symbol_id, name.clone()); + ctx.scopes_mut().rename_binding(scope_id, "arguments", name); + } + + /// Transform the identifier reference for `arguments` if it's affected after transformation. + /// + /// See [`Self::transform_member_expression_for_super`] for the reason. + fn transform_identifier_reference_for_arguments( + &mut self, + ident: &mut IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if !self.should_transform_arguments_identifier(&ident.name, ctx) { + return; + } + + let reference_id = ident.reference_id(); + let symbol_id = ctx.symbols().get_reference(reference_id).symbol_id(); + + let binding = self.arguments_var_stack.last_or_init(|| { + if let Some(symbol_id) = symbol_id { + let arguments_name = ctx.generate_uid_name("arguments"); + let arguments_name_atom = ctx.ast.atom(&arguments_name); + Self::rename_arguments_symbol(symbol_id, arguments_name, ctx); + // Record the symbol ID as a renamed `arguments` variable. + self.renamed_arguments_symbol_ids.insert(symbol_id); + BoundIdentifier::new(arguments_name_atom, symbol_id) + } else { + // We cannot determine the final scope ID of the `arguments` variable insertion, + // because the `arguments` variable will be inserted to a new scope which haven't been created yet, + // so we temporary use root scope id as the fake target scope ID. + let target_scope_id = ctx.scopes().root_scope_id(); + ctx.generate_uid("arguments", target_scope_id, SymbolFlags::FunctionScopedVariable) + } + }); + + // If no symbol ID, it means there is no variable named `arguments` in the scope. + // The following code is just to sync semantics. + if symbol_id.is_none() { + let reference = ctx.symbols_mut().get_reference_mut(reference_id); + reference.set_symbol_id(binding.symbol_id); + ctx.scopes_mut().delete_root_unresolved_reference(&ident.name, reference_id); + ctx.symbols_mut().resolved_references[binding.symbol_id].push(reference_id); + } + + ident.name = binding.name.clone(); + } + + /// Transform the binding identifier for `arguments` if it's affected after transformation. + /// + /// The main work is to rename the `arguments` binding identifier to a new name. + fn transform_binding_identifier_for_arguments( + &mut self, + ident: &mut BindingIdentifier<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + if ctx.current_scope_flags().is_strict_mode() // `arguments` is not allowed to be defined in strict mode. + || !self.should_transform_arguments_identifier(&ident.name, ctx) + { + return; + } + + self.arguments_var_stack.last_or_init(|| { + let arguments_name = ctx.generate_uid_name("arguments"); + ident.name = ctx.ast.atom(&arguments_name); + let symbol_id = ident.symbol_id(); + Self::rename_arguments_symbol(symbol_id, arguments_name, ctx); + // Record the symbol ID as a renamed `arguments` variable. + self.renamed_arguments_symbol_ids.insert(symbol_id); + BoundIdentifier::new(ident.name.clone(), symbol_id) + }); + } + + /// Create a variable declarator looks like `_arguments = arguments;`. + fn create_arguments_var_declarator( + &self, + target_scope_id: ScopeId, + arguments_var: Option>, + ctx: &mut TraverseCtx<'a>, + ) -> Option> { + let arguments_var = arguments_var?; + + // Just a renamed `arguments` variable, we don't need to create a new variable declaration. + if self.renamed_arguments_symbol_ids.contains(&arguments_var.symbol_id) { + return None; + } + + Self::adjust_binding_scope(target_scope_id, &arguments_var, ctx); + let reference = + ctx.create_unbound_ident_reference(SPAN, Atom::from("arguments"), ReferenceFlags::Read); + let mut init = Expression::Identifier(ctx.ast.alloc(reference.clone())); + + // Top level may doesn't have `arguments`, so we need to check it. + // `typeof arguments === "undefined" ? void 0 : arguments;` + if ctx.scopes().root_scope_id() == target_scope_id { + let argument = Expression::Identifier(ctx.ast.alloc(reference)); + let typeof_arguments = ctx.ast.expression_unary(SPAN, UnaryOperator::Typeof, argument); + let undefined_literal = ctx.ast.expression_string_literal(SPAN, "undefined"); + let test = ctx.ast.expression_binary( + SPAN, + typeof_arguments, + BinaryOperator::StrictEquality, + undefined_literal, + ); + init = ctx.ast.expression_conditional(SPAN, test, ctx.ast.void_0(SPAN), init); + } + + Some(ctx.ast.variable_declarator( + SPAN, + VariableDeclarationKind::Var, + arguments_var.create_binding_pattern(ctx), + Some(init), + false, + )) + } + /// Insert variable statement at the top of the statements. fn insert_variable_statement_at_the_top_of_statements( &mut self, target_scope_id: ScopeId, statements: &mut ArenaVec<'a, Statement<'a>>, this_var: Option>, + arguments_var: Option>, ctx: &mut TraverseCtx<'a>, ) { + // `_arguments = arguments;` + let arguments = self.create_arguments_var_declarator(target_scope_id, arguments_var, ctx); + + let is_class_method_like = Self::is_class_method_like_ancestor(ctx.parent()); + let declarations_count = usize::from(arguments.is_some()) + + if is_class_method_like { + self.super_methods.as_ref().map_or(0, FxHashMap::len) + } else { + 0 + } + + usize::from(this_var.is_some()); + + // Exit if no declarations to be inserted + if declarations_count == 0 { + return; + } + + let mut declarations = ctx.ast.vec_with_capacity(declarations_count); + + if let Some(arguments) = arguments { + declarations.push(arguments); + } + // `_superprop_getSomething = () => super.getSomething;` - let mut declarations = if Self::is_class_method_like_ancestor(ctx.parent()) { + if is_class_method_like { if let Some(super_methods) = self.super_methods.as_mut() { - let mut declarations = ctx.ast.vec_with_capacity(super_methods.len() + 1); declarations.extend(super_methods.drain().map(|(_, super_method)| { Self::generate_super_method(target_scope_id, super_method, ctx) })); - declarations - } else { - ctx.ast.vec_with_capacity(1) } - } else { - ctx.ast.vec_with_capacity(1) - }; + } // `_this = this;` if let Some(this_var) = this_var { @@ -823,10 +1027,7 @@ impl<'a> ArrowFunctionConverter<'a> { declarations.push(variable_declarator); } - // If there are no declarations, we don't need to insert a variable declaration. - if declarations.is_empty() { - return; - } + debug_assert_eq!(declarations_count, declarations.len()); let stmt = ctx.ast.alloc_variable_declaration( SPAN, diff --git a/crates/oxc_transformer/src/common/mod.rs b/crates/oxc_transformer/src/common/mod.rs index 8fc341179f10c8..6c372b4a52f19b 100644 --- a/crates/oxc_transformer/src/common/mod.rs +++ b/crates/oxc_transformer/src/common/mod.rs @@ -103,4 +103,20 @@ impl<'a, 'ctx> Traverse<'a> for Common<'a, 'ctx> { fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) { self.arrow_function_converter.exit_expression(expr, ctx); } + + fn enter_binding_identifier( + &mut self, + node: &mut BindingIdentifier<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.arrow_function_converter.enter_binding_identifier(node, ctx); + } + + fn enter_identifier_reference( + &mut self, + node: &mut IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.arrow_function_converter.enter_identifier_reference(node, ctx); + } } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 474564f4339b0c..1ff1d32c6620e5 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -190,6 +190,22 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> { self.x2_es2020.enter_big_int_literal(node, ctx); } + fn enter_binding_identifier( + &mut self, + node: &mut BindingIdentifier<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.common.enter_binding_identifier(node, ctx); + } + + fn enter_identifier_reference( + &mut self, + node: &mut IdentifierReference<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.common.enter_identifier_reference(node, ctx); + } + fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, ctx: &mut TraverseCtx<'a>) { if let Some(typescript) = self.x0_typescript.as_mut() { typescript.enter_binding_pattern(pat, ctx); diff --git a/tasks/transform_conformance/snapshots/oxc.snap.md b/tasks/transform_conformance/snapshots/oxc.snap.md index 1078e19e21a031..1cc7879ddaed13 100644 --- a/tasks/transform_conformance/snapshots/oxc.snap.md +++ b/tasks/transform_conformance/snapshots/oxc.snap.md @@ -1,6 +1,6 @@ commit: d20b314c -Passed: 82/92 +Passed: 85/95 # All Passed: * babel-plugin-transform-class-static-block diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/input.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/input.js new file mode 100644 index 00000000000000..5b43966205ad82 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/input.js @@ -0,0 +1,4 @@ +const ArgumentsAssignment = async () => { + let arguments = arguments; + console.log(arguments); +}; diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/output.js new file mode 100644 index 00000000000000..097d15571fd88f --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/assign/output.js @@ -0,0 +1,9 @@ +const ArgumentsAssignment = /*#__PURE__*/function () { + var _ref = babelHelpers.asyncToGenerator(function* () { + let _arguments = _arguments; + console.log(_arguments); + }); + return function ArgumentsAssignment() { + return _ref.apply(this, arguments); + }; +}(); diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/input.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/input.js new file mode 100644 index 00000000000000..eb6b94e8fc8e34 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/input.js @@ -0,0 +1,7 @@ +class Cls { + async method() { + () => { + console.log(arguments); + } + } +} diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/output.js new file mode 100644 index 00000000000000..5650ed3766c7a1 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/async-method/output.js @@ -0,0 +1,10 @@ +class Cls { + method() { + var _arguments = arguments; + return babelHelpers.asyncToGenerator(function* () { + () => { + console.log(_arguments); + }; + })(); + } +} diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/input.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/input.js new file mode 100644 index 00000000000000..640d39129b23a6 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/input.js @@ -0,0 +1,7 @@ +const ArrowFunction = async () => { + { + var arguments = arguments; + console.log(arguments); + } + console.log(arguments); +}; diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/output.js new file mode 100644 index 00000000000000..1d962da7d59c91 --- /dev/null +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/arguments/nested-block/output.js @@ -0,0 +1,12 @@ +const ArrowFunction = /*#__PURE__*/function () { + var _ref = babelHelpers.asyncToGenerator(function* () { + { + var _arguments = _arguments; + console.log(_arguments); + } + console.log(_arguments); + }); + return function ArrowFunction() { + return _ref.apply(this, arguments); + }; +}(); From 7b7555a0abc99e689d9825fb5a7a03c776502980 Mon Sep 17 00:00:00 2001 From: Nicholas Rayburn <52075362+nrayburn-tech@users.noreply.github.com> Date: Sun, 17 Nov 2024 00:23:00 -0600 Subject: [PATCH 016/121] docs(website): Link to specific ref when generating website docs (#7324) Currently the website links to main which is subject to change without an update to the website. This updates the website to link to the specific commit that was used when the website was published. Feel free to cleanup anything in this PR. --- justfile | 2 +- tasks/website/src/linter/rules/doc_page.rs | 11 ++++++----- tasks/website/src/linter/rules/mod.rs | 13 +++++++++---- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/justfile b/justfile index fe94849a8d3976..6f8f8f80e518f0 100755 --- a/justfile +++ b/justfile @@ -207,6 +207,6 @@ clone-submodule dir url sha: cd {{dir}} ; git fetch --depth=1 origin {{sha}} ; git reset --hard {{sha}} website path: - cargo run -p website -- linter-rules --table {{path}}/src/docs/guide/usage/linter/generated-rules.md --rule-docs {{path}}/src/docs/guide/usage/linter/rules + cargo run -p website -- linter-rules --table {{path}}/src/docs/guide/usage/linter/generated-rules.md --rule-docs {{path}}/src/docs/guide/usage/linter/rules --git-ref $(git rev-parse HEAD) cargo run -p website -- linter-cli > {{path}}/src/docs/guide/usage/linter/generated-cli.md cargo run -p website -- linter-schema-markdown > {{path}}/src/docs/guide/usage/linter/generated-config.md diff --git a/tasks/website/src/linter/rules/doc_page.rs b/tasks/website/src/linter/rules/doc_page.rs index a4c4a5f40bacc9..9c316db36a932a 100644 --- a/tasks/website/src/linter/rules/doc_page.rs +++ b/tasks/website/src/linter/rules/doc_page.rs @@ -10,7 +10,7 @@ use oxc_linter::table::RuleTableRow; use super::HtmlWriter; -pub fn render_rule_docs_page(rule: &RuleTableRow) -> Result { +pub fn render_rule_docs_page(rule: &RuleTableRow, git_ref: &str) -> Result { const APPROX_FIX_CATEGORY_AND_PLUGIN_LEN: usize = 512; let RuleTableRow { name, documentation, plugin, turned_on_by_default, autofix, category } = rule; @@ -52,22 +52,23 @@ pub fn render_rule_docs_page(rule: &RuleTableRow) -> Result writeln!(page, "\n{}", *docs)?; } - let rule_source = rule_source(rule); + let rule_source = rule_source(rule, git_ref); writeln!(page, "\n## References")?; writeln!(page, "- [Rule Source]({rule_source})")?; Ok(page.into()) } -fn rule_source(rule: &RuleTableRow) -> String { +fn rule_source(rule: &RuleTableRow, git_ref: &str) -> String { use std::sync::OnceLock; use project_root::get_project_root; - const GITHUB_URL: &str = "https://github.com/oxc-project/oxc/blob/main"; + const GITHUB_BASE_URL: &str = "https://github.com/oxc-project/oxc/blob/"; const LINT_RULES_DIR: &str = "crates/oxc_linter/src/rules"; static ROOT: OnceLock = OnceLock::new(); + let github_url: String = GITHUB_BASE_URL.to_owned() + git_ref; let root = ROOT.get_or_init(|| get_project_root().unwrap()); // Some rules are folders with a mod.rs file, others are just a rust file @@ -82,5 +83,5 @@ fn rule_source(rule: &RuleTableRow) -> String { assert!(rule_path.exists(), "Rule source not found: {}", rule_path.display()); assert!(rule_path.is_file(), "Rule source is not a file: {}", rule_path.display()); - rule_path.to_string_lossy().replace(root.to_str().unwrap(), GITHUB_URL) + rule_path.to_string_lossy().replace(root.to_str().unwrap(), github_url.as_str()) } diff --git a/tasks/website/src/linter/rules/mod.rs b/tasks/website/src/linter/rules/mod.rs index 6bb02421aace42..a3e5bd495ca5b2 100644 --- a/tasks/website/src/linter/rules/mod.rs +++ b/tasks/website/src/linter/rules/mod.rs @@ -21,6 +21,8 @@ Arguments: -t,--table Path to file where rule markdown table will be saved. -r,--rule-docs Path to directory where rule doc pages will be saved. A directory will be created if one doesn't exist. + --git-ref Git commit, branch, or tag to be used in the generated links. + If not supplied, `main` will be used. -h,--help Show this help message. "; @@ -28,6 +30,7 @@ Arguments: /// `cargo run -p website linter-rules --table /// /path/to/oxc/oxc-project.github.io/src/docs/guide/usage/linter/generated-rules.md /// --rule-docs /path/to/oxc/oxc-project.github.io/src/docs/guide/usage/linter/rules +/// --git-ref dc9dc03872101c15b0d02f05ce45705565665829 /// ` /// pub fn print_rules(mut args: Arguments) { @@ -37,7 +40,7 @@ pub fn print_rules(mut args: Arguments) { return; } - let table = RuleTable::new(); + let git_ref = args.opt_value_from_str("--git-ref").unwrap(); let table_path = args.opt_value_from_str::<_, PathBuf>(["-t", "--table"]).unwrap(); let rules_dir = args.opt_value_from_str::<_, PathBuf>(["-r", "--rule-docs"]).unwrap(); @@ -52,6 +55,8 @@ pub fn print_rules(mut args: Arguments) { } }); + let table = RuleTable::new(); + if let Some(table_path) = table_path { let table_path = pwd.join(table_path).canonicalize().unwrap(); @@ -71,13 +76,13 @@ pub fn print_rules(mut args: Arguments) { !rules_dir.is_file(), "Cannot write rule docs to a file. Please specify a directory." ); - write_rule_doc_pages(&table, &rules_dir); + write_rule_doc_pages(&table, &rules_dir, git_ref.unwrap_or("main".to_string()).as_str()); } println!("Done."); } -fn write_rule_doc_pages(table: &RuleTable, outdir: &Path) { +fn write_rule_doc_pages(table: &RuleTable, outdir: &Path, git_ref: &str) { for rule in table.sections.iter().flat_map(|section| §ion.rows) { let plugin_path = outdir.join(&rule.plugin); fs::create_dir_all(&plugin_path).unwrap(); @@ -86,7 +91,7 @@ fn write_rule_doc_pages(table: &RuleTable, outdir: &Path) { fs::remove_file(&page_path).unwrap(); } println!("{}", page_path.display()); - let docs = render_rule_docs_page(rule).unwrap(); + let docs = render_rule_docs_page(rule, git_ref).unwrap(); fs::write(&page_path, docs).unwrap(); } } From 5cfe0b623e59a6b9ad56a37704b08b989f44a773 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:55 +0000 Subject: [PATCH 017/121] refactor(transformer/arrow-function): `generate_super_binding_name` take `&str` and `&TraverseCtx` (#7310) Pure refactor. Take `&str` rather than `&Atom` (1 less indirection) and `&TraverseCtx<'a>` (more conventional). --- .../src/common/arrow_function_converter.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index acde13c691ff34..ef7391ab28c48a 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -90,7 +90,7 @@ use rustc_hash::{FxHashMap, FxHashSet}; use oxc_allocator::{Box as ArenaBox, String as ArenaString, Vec as ArenaVec}; -use oxc_ast::{ast::*, AstBuilder, NONE}; +use oxc_ast::{ast::*, NONE}; use oxc_data_structures::stack::SparseStack; use oxc_semantic::{ReferenceFlags, SymbolId}; use oxc_span::{CompactStr, SPAN}; @@ -568,7 +568,7 @@ impl<'a> ArrowFunctionConverter<'a> { let super_methods = self.super_methods.as_mut()?; let mut argument = None; - let mut property = Atom::empty(); + let mut property = ""; let init = match expr.to_member_expression_mut() { MemberExpression::ComputedMemberExpression(computed_member) => { if !matches!(computed_member.object, Expression::Super(_)) { @@ -585,7 +585,7 @@ impl<'a> ArrowFunctionConverter<'a> { } // Used to generate the name of the arrow function. - property = static_member.property.name.clone(); + property = static_member.property.name.as_str(); ctx.ast.move_expression(expr) } MemberExpression::PrivateFieldExpression(_) => { @@ -594,8 +594,7 @@ impl<'a> ArrowFunctionConverter<'a> { } }; - let binding_name = - Self::generate_super_binding_name(assign_value.is_some(), &property, ctx.ast); + let binding_name = Self::generate_super_binding_name(assign_value.is_some(), property, ctx); let super_info = super_methods.entry(binding_name.clone()).or_insert_with(|| { let binding = ctx .generate_uid_in_current_scope(&binding_name, SymbolFlags::FunctionScopedVariable); @@ -801,10 +800,10 @@ impl<'a> ArrowFunctionConverter<'a> { /// Generate a binding name for the super method, like `_superprop_getXXX`. fn generate_super_binding_name( is_assignment: bool, - property: &Atom<'a>, - ast: AstBuilder<'a>, + property: &str, + ctx: &TraverseCtx<'a>, ) -> Atom<'a> { - let mut name = ArenaString::new_in(ast.allocator); + let mut name = ArenaString::new_in(ctx.ast.allocator); name.push_str("superprop_"); if is_assignment { @@ -820,7 +819,7 @@ impl<'a> ArrowFunctionConverter<'a> { if property.len() > 1 { name.push_str(&property[1..]); } - ast.atom(name.into_bump_str()) + ctx.ast.atom(name.into_bump_str()) } /// Whether to transform the `arguments` identifier. From 389b84e4ff6828357d4ecfb0ff1b8a5780f9dd56 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:55 +0000 Subject: [PATCH 018/121] fix(transformer/arrow-function): handle unicode when capitalizing property name (#7311) Previously was assuming property name starts with an ASCII character. If it started with a multi-byte unicode char, `&property[1..]` would panic. --- .../src/common/arrow_function_converter.rs | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index ef7391ab28c48a..3eb9ac3a9668eb 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -812,13 +812,21 @@ impl<'a> ArrowFunctionConverter<'a> { name.push_str("get"); } - // Capitalize the first letter of the property name. - if let Some(first_byte) = property.as_bytes().first() { - name.push(first_byte.to_ascii_uppercase() as char); - } - if property.len() > 1 { - name.push_str(&property[1..]); + // Capitalize the first letter of the property name + if let Some(&first_byte) = property.as_bytes().first() { + if first_byte.is_ascii() { + name.push(first_byte.to_ascii_uppercase() as char); + if property.len() > 1 { + name.push_str(&property[1..]); + } + } else { + let mut chars = property.chars(); + let first_char = chars.next().unwrap(); + name.extend(first_char.to_uppercase()); + name.push_str(chars.as_str()); + } } + ctx.ast.atom(name.into_bump_str()) } From 0a2470399e62d96f37549f1893d777715f20e391 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:56 +0000 Subject: [PATCH 019/121] perf(transformer/arrow-function): optimize `generate_super_binding_name` (#7312) Optimize this function in various ways: * Return a static `Atom` (rather than allocating into arena) if no `property`. * Reserve capacity for `ArenaString` at start. * Make path for unicode identifiers (very rare case) `#[cold]` and `#[inline(never)]`. * Slightly faster uppercase conversion. --- .../src/common/arrow_function_converter.rs | 50 +++++++++++++------ 1 file changed, 34 insertions(+), 16 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 3eb9ac3a9668eb..abf7ac32ac4f9c 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -797,34 +797,52 @@ impl<'a> ArrowFunctionConverter<'a> { ) } - /// Generate a binding name for the super method, like `_superprop_getXXX`. + /// Generate a binding name for the super method, like `superprop_getXXX`. fn generate_super_binding_name( is_assignment: bool, property: &str, ctx: &TraverseCtx<'a>, ) -> Atom<'a> { - let mut name = ArenaString::new_in(ctx.ast.allocator); + let start = + if is_assignment { Atom::from("superprop_set") } else { Atom::from("superprop_get") }; - name.push_str("superprop_"); - if is_assignment { - name.push_str("set"); - } else { - name.push_str("get"); - } + let Some(&first_byte) = property.as_bytes().first() else { + return start; + }; - // Capitalize the first letter of the property name - if let Some(&first_byte) = property.as_bytes().first() { - if first_byte.is_ascii() { - name.push(first_byte.to_ascii_uppercase() as char); - if property.len() > 1 { - name.push_str(&property[1..]); - } - } else { + let mut name = + ArenaString::with_capacity_in(start.len() + property.len(), ctx.ast.allocator); + name.push_str(start.as_str()); + + // Capitalize the first letter of the property name. + // Fast path for ASCII (very common case). + // TODO(improve-on-babel): We could just use format `superprop_get_prop` and avoid capitalizing. + if first_byte.is_ascii() { + // We know `IdentifierName`s begin with `a-z`, `A-Z`, `_` or `$` if ASCII, + // so can use a slightly cheaper conversion than `u8::to_ascii_uppercase`. + // Adapted from `u8::to_ascii_uppercase`'s implementation. + // https://godbolt.org/z/5Txa6Pv9z + #[inline] + fn ascii_ident_first_char_uppercase(b: u8) -> u8 { + const ASCII_CASE_MASK: u8 = 0b0010_0000; + let is_lower_case = b >= b'a'; + b ^ (u8::from(is_lower_case) * ASCII_CASE_MASK) + } + + name.push(ascii_ident_first_char_uppercase(first_byte) as char); + if property.len() > 1 { + name.push_str(&property[1..]); + } + } else { + #[cold] + #[inline(never)] + fn push_unicode(property: &str, name: &mut ArenaString) { let mut chars = property.chars(); let first_char = chars.next().unwrap(); name.extend(first_char.to_uppercase()); name.push_str(chars.as_str()); } + push_unicode(property, &mut name); } ctx.ast.atom(name.into_bump_str()) From 5d853869ebd6cbaf171cc6658efc03c17b0ae4db Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:57 +0000 Subject: [PATCH 020/121] refactor(transformer/arrow-functions): use `IndexMap` for `super` getter/setters (#7317) Generate getter/setter declarations in same order as Babel by using `IndexMap` instead of `HashMap` to store `super` getter/setter method details. --- .../src/common/arrow_function_converter.rs | 17 ++++++++++++----- .../test/fixtures/super/assign/output.js | 10 +++++----- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index abf7ac32ac4f9c..2f2b2d3d4e679e 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -87,7 +87,10 @@ //! The Implementation based on //! -use rustc_hash::{FxHashMap, FxHashSet}; +use std::hash::BuildHasherDefault; + +use indexmap::IndexMap; +use rustc_hash::{FxHashSet, FxHasher}; use oxc_allocator::{Box as ArenaBox, String as ArenaString, Vec as ArenaVec}; use oxc_ast::{ast::*, NONE}; @@ -102,6 +105,8 @@ use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx}; use crate::EnvOptions; +type FxIndexMap = IndexMap>; + /// Mode for arrow function conversion #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ArrowFunctionConverterMode { @@ -129,7 +134,9 @@ pub struct ArrowFunctionConverter<'a> { this_var_stack: SparseStack>, arguments_var_stack: SparseStack>, renamed_arguments_symbol_ids: FxHashSet, - super_methods: Option, SuperMethodInfo<'a>>>, + // TODO(improve-on-babel): `FxHashMap` would suffice here. Iteration order is not important. + // Only using `FxIndexMap` for predictable iteration order to match Babel's output. + super_methods: Option, SuperMethodInfo<'a>>>, } impl<'a> ArrowFunctionConverter<'a> { @@ -187,7 +194,7 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { self.arguments_var_stack.push(None); if self.is_async_only() && func.r#async && Self::is_class_method_like_ancestor(ctx.parent()) { - self.super_methods = Some(FxHashMap::default()); + self.super_methods = Some(FxIndexMap::default()); } } @@ -1013,7 +1020,7 @@ impl<'a> ArrowFunctionConverter<'a> { let is_class_method_like = Self::is_class_method_like_ancestor(ctx.parent()); let declarations_count = usize::from(arguments.is_some()) + if is_class_method_like { - self.super_methods.as_ref().map_or(0, FxHashMap::len) + self.super_methods.as_ref().map_or(0, FxIndexMap::len) } else { 0 } @@ -1033,7 +1040,7 @@ impl<'a> ArrowFunctionConverter<'a> { // `_superprop_getSomething = () => super.getSomething;` if is_class_method_like { if let Some(super_methods) = self.super_methods.as_mut() { - declarations.extend(super_methods.drain().map(|(_, super_method)| { + declarations.extend(super_methods.drain(..).map(|(_, super_method)| { Self::generate_super_method(target_scope_id, super_method, ctx) })); } diff --git a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/super/assign/output.js b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/super/assign/output.js index 1e69ce6904e0db..e00541768cb612 100644 --- a/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/super/assign/output.js +++ b/tasks/transform_conformance/tests/babel-plugin-transform-async-to-generator/test/fixtures/super/assign/output.js @@ -1,15 +1,15 @@ const Obj = { value: 0, method() { - var _superprop_getObject = () => super.object, - _superprop_set = (_prop, _value) => super[_prop] = _value, - _superprop_setValue = _value2 => super.value = _value2; + var _superprop_setValue = (_value) => (super.value = _value), + _superprop_set = (_prop, _value2) => (super[_prop] = _value2), + _superprop_getObject = () => super.object; return babelHelpers.asyncToGenerator(function* () { _superprop_setValue(true); () => { - _superprop_set('value', true); + _superprop_set("value", true); _superprop_getObject().value = true; }; })(); } -}; \ No newline at end of file +}; From e09d2df448b58a115c9b6133e243f2acff754df5 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:57 +0000 Subject: [PATCH 021/121] perf(transformer/arrow-function): create super method binding names lazily (#7313) Key `super` getter/setter hash map with original property name `&str`, instead of generated binding name. This allows a couple of improvements: * Generate binding names for `super` getters/setters lazily, only when they're created, rather than every time you encounter a `super`. * Don't allocate strings into arena which are never used as part of AST. Use `CompactString` for building those strings instead. --- Cargo.lock | 1 + crates/oxc_transformer/Cargo.toml | 1 + .../src/common/arrow_function_converter.rs | 69 ++++++++++--------- 3 files changed, 40 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b2c517e01547b2..dff09b9f4c9d00 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2062,6 +2062,7 @@ name = "oxc_transformer" version = "0.36.0" dependencies = [ "base64", + "compact_str", "cow-utils", "dashmap 6.1.0", "indexmap", diff --git a/crates/oxc_transformer/Cargo.toml b/crates/oxc_transformer/Cargo.toml index ce23b97be84b93..6ed2e2cfcd6878 100644 --- a/crates/oxc_transformer/Cargo.toml +++ b/crates/oxc_transformer/Cargo.toml @@ -35,6 +35,7 @@ oxc_syntax = { workspace = true, features = ["to_js_string"] } oxc_traverse = { workspace = true } base64 = { workspace = true } +compact_str = { workspace = true } cow-utils = { workspace = true } dashmap = { workspace = true } indexmap = { workspace = true } diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 2f2b2d3d4e679e..50aea057d9d949 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -89,10 +89,11 @@ use std::hash::BuildHasherDefault; +use compact_str::CompactString; use indexmap::IndexMap; use rustc_hash::{FxHashSet, FxHasher}; -use oxc_allocator::{Box as ArenaBox, String as ArenaString, Vec as ArenaVec}; +use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; use oxc_ast::{ast::*, NONE}; use oxc_data_structures::stack::SparseStack; use oxc_semantic::{ReferenceFlags, SymbolId}; @@ -120,13 +121,20 @@ pub enum ArrowFunctionConverterMode { AsyncOnly, } +#[derive(PartialEq, Eq, Hash)] +struct SuperMethodKey<'a> { + /// If it is true, the method should accept a value parameter. + is_assignment: bool, + /// Name of property getter/setter is for. + /// Empty string for computed properties. + property: &'a str, +} + struct SuperMethodInfo<'a> { binding: BoundIdentifier<'a>, super_expr: Expression<'a>, /// If it is true, the method should accept a prop parameter. is_computed: bool, - /// If it is true, the method should accept a value parameter. - is_assignment: bool, } pub struct ArrowFunctionConverter<'a> { @@ -136,7 +144,7 @@ pub struct ArrowFunctionConverter<'a> { renamed_arguments_symbol_ids: FxHashSet, // TODO(improve-on-babel): `FxHashMap` would suffice here. Iteration order is not important. // Only using `FxIndexMap` for predictable iteration order to match Babel's output. - super_methods: Option, SuperMethodInfo<'a>>>, + super_methods: Option, SuperMethodInfo<'a>>>, } impl<'a> ArrowFunctionConverter<'a> { @@ -601,16 +609,13 @@ impl<'a> ArrowFunctionConverter<'a> { } }; - let binding_name = Self::generate_super_binding_name(assign_value.is_some(), property, ctx); - let super_info = super_methods.entry(binding_name.clone()).or_insert_with(|| { + let is_assignment = assign_value.is_some(); + let key = SuperMethodKey { is_assignment, property }; + let super_info = super_methods.entry(key).or_insert_with(|| { + let binding_name = Self::generate_super_binding_name(is_assignment, property); let binding = ctx .generate_uid_in_current_scope(&binding_name, SymbolFlags::FunctionScopedVariable); - SuperMethodInfo { - binding, - super_expr: init, - is_computed: argument.is_some(), - is_assignment: assign_value.is_some(), - } + SuperMethodInfo { binding, super_expr: init, is_computed: argument.is_some() } }); let callee = super_info.binding.create_read_expression(ctx); @@ -729,10 +734,10 @@ impl<'a> ArrowFunctionConverter<'a> { fn generate_super_method( target_scope_id: ScopeId, super_method: SuperMethodInfo<'a>, + is_assignment: bool, ctx: &mut TraverseCtx<'a>, ) -> VariableDeclarator<'a> { - let SuperMethodInfo { binding, super_expr: mut init, is_computed, is_assignment } = - super_method; + let SuperMethodInfo { binding, super_expr: mut init, is_computed } = super_method; Self::adjust_binding_scope(target_scope_id, &binding, ctx); let scope_id = @@ -805,22 +810,17 @@ impl<'a> ArrowFunctionConverter<'a> { } /// Generate a binding name for the super method, like `superprop_getXXX`. - fn generate_super_binding_name( - is_assignment: bool, - property: &str, - ctx: &TraverseCtx<'a>, - ) -> Atom<'a> { - let start = - if is_assignment { Atom::from("superprop_set") } else { Atom::from("superprop_get") }; + fn generate_super_binding_name(is_assignment: bool, property: &str) -> CompactString { + let mut name = if is_assignment { + CompactString::const_new("superprop_set") + } else { + CompactString::const_new("superprop_get") + }; let Some(&first_byte) = property.as_bytes().first() else { - return start; + return name; }; - let mut name = - ArenaString::with_capacity_in(start.len() + property.len(), ctx.ast.allocator); - name.push_str(start.as_str()); - // Capitalize the first letter of the property name. // Fast path for ASCII (very common case). // TODO(improve-on-babel): We could just use format `superprop_get_prop` and avoid capitalizing. @@ -843,7 +843,7 @@ impl<'a> ArrowFunctionConverter<'a> { } else { #[cold] #[inline(never)] - fn push_unicode(property: &str, name: &mut ArenaString) { + fn push_unicode(property: &str, name: &mut CompactString) { let mut chars = property.chars(); let first_char = chars.next().unwrap(); name.extend(first_char.to_uppercase()); @@ -852,7 +852,7 @@ impl<'a> ArrowFunctionConverter<'a> { push_unicode(property, &mut name); } - ctx.ast.atom(name.into_bump_str()) + name } /// Whether to transform the `arguments` identifier. @@ -1037,11 +1037,18 @@ impl<'a> ArrowFunctionConverter<'a> { declarations.push(arguments); } - // `_superprop_getSomething = () => super.getSomething;` + // `_superprop_getSomething = () => super.something;` + // `_superprop_setSomething = _value => super.something = _value;` + // `_superprop_set = (_prop, _value) => super[_prop] = _value;` if is_class_method_like { if let Some(super_methods) = self.super_methods.as_mut() { - declarations.extend(super_methods.drain(..).map(|(_, super_method)| { - Self::generate_super_method(target_scope_id, super_method, ctx) + declarations.extend(super_methods.drain(..).map(|(key, super_method)| { + Self::generate_super_method( + target_scope_id, + super_method, + key.is_assignment, + ctx, + ) })); } } From ea08c1f495f842cfa01cd79afd2d7e00b335412c Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:58 +0000 Subject: [PATCH 022/121] refactor(transformer/arrow-function): reserve correct capacity for `Vec` (#7319) --- crates/oxc_transformer/src/common/arrow_function_converter.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 50aea057d9d949..f0b6ab18304f28 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -743,7 +743,8 @@ impl<'a> ArrowFunctionConverter<'a> { let scope_id = ctx.create_child_scope(target_scope_id, ScopeFlags::Arrow | ScopeFlags::Function); - let mut items = ctx.ast.vec_with_capacity(2); + let mut items = + ctx.ast.vec_with_capacity(usize::from(is_computed) + usize::from(is_assignment)); // Create a parameter for the prop if it's a computed member expression. if is_computed { From 871e19bea29c4d048f18a139a30f536c0fe57bc8 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 05:08:59 +0000 Subject: [PATCH 023/121] refactor(transformer/arrow-function): comments on possible improvement (#7320) --- crates/oxc_transformer/src/common/arrow_function_converter.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index f0b6ab18304f28..26ae678351ca9f 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -748,6 +748,8 @@ impl<'a> ArrowFunctionConverter<'a> { // Create a parameter for the prop if it's a computed member expression. if is_computed { + // TODO(improve-on-babel): No need for UID here. Just `prop` would be fine as there's nothing + // in `prop => super[prop]` or `(prop, value) => super[prop] = value` which can clash. let param_binding = ctx.generate_uid("prop", scope_id, SymbolFlags::FunctionScopedVariable); let param = ctx.ast.formal_parameter( @@ -771,6 +773,8 @@ impl<'a> ArrowFunctionConverter<'a> { // Create a parameter for the value if it's an assignment. if is_assignment { + // TODO(improve-on-babel): No need for UID here. Just `value` would be fine as there's nothing + // in `value => super.prop = value` or `(prop, value) => super[prop] = value` which can clash. let param_binding = ctx.generate_uid("value", scope_id, SymbolFlags::FunctionScopedVariable); let param = ctx.ast.formal_parameter( From 26d3e96aca6d0a53e6518471f6692cdbdce6a8e8 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 10:49:16 +0000 Subject: [PATCH 024/121] perf(transformer/arrow-functions): store state of whether arguments needs transform (#7321) Track whether `arguments` needs to be transformed. If it doesn't, can skip expensive checks for whether `IdentifierReference`s and `BindingIdentifier`s names are `arguments` or not. This recovers about half the performance hit of #7234. --- .../src/common/arrow_function_converter.rs | 74 ++++++++++--------- crates/oxc_transformer/src/common/mod.rs | 16 ++++ crates/oxc_transformer/src/lib.rs | 9 +++ 3 files changed, 64 insertions(+), 35 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 26ae678351ca9f..e1b80ff69c4c5e 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -95,7 +95,7 @@ use rustc_hash::{FxHashSet, FxHasher}; use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec}; use oxc_ast::{ast::*, NONE}; -use oxc_data_structures::stack::SparseStack; +use oxc_data_structures::stack::{NonEmptyStack, SparseStack}; use oxc_semantic::{ReferenceFlags, SymbolId}; use oxc_span::{CompactStr, SPAN}; use oxc_syntax::{ @@ -141,6 +141,7 @@ pub struct ArrowFunctionConverter<'a> { mode: ArrowFunctionConverterMode, this_var_stack: SparseStack>, arguments_var_stack: SparseStack>, + arguments_needs_transform_stack: NonEmptyStack, renamed_arguments_symbol_ids: FxHashSet, // TODO(improve-on-babel): `FxHashMap` would suffice here. Iteration order is not important. // Only using `FxIndexMap` for predictable iteration order to match Babel's output. @@ -161,6 +162,7 @@ impl<'a> ArrowFunctionConverter<'a> { mode, this_var_stack: SparseStack::new(), arguments_var_stack: SparseStack::new(), + arguments_needs_transform_stack: NonEmptyStack::new(false), renamed_arguments_symbol_ids: FxHashSet::default(), super_methods: None, } @@ -237,6 +239,35 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { ); } + fn enter_arrow_function_expression( + &mut self, + arrow: &mut ArrowFunctionExpression<'a>, + _ctx: &mut TraverseCtx<'a>, + ) { + if self.is_async_only() { + let previous = *self.arguments_needs_transform_stack.last(); + self.arguments_needs_transform_stack.push(previous || arrow.r#async); + } + } + + fn enter_function_body(&mut self, _body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { + if self.is_async_only() { + // Ignore arrow functions + if let Ancestor::FunctionBody(func) = ctx.parent() { + let is_async_method = + *func.r#async() && Self::is_class_method_like_ancestor(ctx.ancestor(1)); + self.arguments_needs_transform_stack.push(is_async_method); + } + } + } + + fn exit_function_body(&mut self, _body: &mut FunctionBody<'a>, _ctx: &mut TraverseCtx<'a>) { + // This covers exiting either a `Function` or an `ArrowFunctionExpression` + if self.is_async_only() { + self.arguments_needs_transform_stack.pop(); + } + } + fn enter_static_block(&mut self, _block: &mut StaticBlock<'a>, _ctx: &mut TraverseCtx<'a>) { if self.is_disabled() { return; @@ -361,6 +392,7 @@ impl<'a> ArrowFunctionConverter<'a> { } /// Check if arrow function conversion has enabled for transform async arrow functions + #[inline] fn is_async_only(&self) -> bool { self.mode == ArrowFunctionConverterMode::AsyncOnly } @@ -860,37 +892,6 @@ impl<'a> ArrowFunctionConverter<'a> { name } - /// Whether to transform the `arguments` identifier. - fn should_transform_arguments_identifier(&self, name: &str, ctx: &mut TraverseCtx<'a>) -> bool { - self.is_async_only() && name == "arguments" && Self::is_affected_arguments_identifier(ctx) - } - - /// Check if the `arguments` identifier is affected by the transformation. - fn is_affected_arguments_identifier(ctx: &mut TraverseCtx<'a>) -> bool { - let mut ancestors = ctx.ancestors().skip(1); - while let Some(ancestor) = ancestors.next() { - match ancestor { - Ancestor::ArrowFunctionExpressionParams(arrow) => { - if *arrow.r#async() { - return true; - } - } - Ancestor::ArrowFunctionExpressionBody(arrow) => { - if *arrow.r#async() { - return true; - } - } - Ancestor::FunctionBody(func) => { - return *func.r#async() - && Self::is_class_method_like_ancestor(ancestors.next().unwrap()); - } - _ => (), - } - } - - false - } - /// Rename the `arguments` symbol to a new name. fn rename_arguments_symbol(symbol_id: SymbolId, name: CompactStr, ctx: &mut TraverseCtx<'a>) { let scope_id = ctx.symbols().get_scope_id(symbol_id); @@ -906,7 +907,8 @@ impl<'a> ArrowFunctionConverter<'a> { ident: &mut IdentifierReference<'a>, ctx: &mut TraverseCtx<'a>, ) { - if !self.should_transform_arguments_identifier(&ident.name, ctx) { + let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); + if !arguments_needs_transform || &ident.name != "arguments" { return; } @@ -950,8 +952,10 @@ impl<'a> ArrowFunctionConverter<'a> { ident: &mut BindingIdentifier<'a>, ctx: &mut TraverseCtx<'a>, ) { - if ctx.current_scope_flags().is_strict_mode() // `arguments` is not allowed to be defined in strict mode. - || !self.should_transform_arguments_identifier(&ident.name, ctx) + let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); + if !arguments_needs_transform + || ctx.current_scope_flags().is_strict_mode() // `arguments` is not allowed to be defined in strict mode + || &ident.name != "arguments" { return; } diff --git a/crates/oxc_transformer/src/common/mod.rs b/crates/oxc_transformer/src/common/mod.rs index 6c372b4a52f19b..c84b29e37c8fc2 100644 --- a/crates/oxc_transformer/src/common/mod.rs +++ b/crates/oxc_transformer/src/common/mod.rs @@ -72,6 +72,22 @@ impl<'a, 'ctx> Traverse<'a> for Common<'a, 'ctx> { self.arrow_function_converter.exit_function(func, ctx); } + fn enter_arrow_function_expression( + &mut self, + arrow: &mut ArrowFunctionExpression<'a>, + ctx: &mut TraverseCtx<'a>, + ) { + self.arrow_function_converter.enter_arrow_function_expression(arrow, ctx); + } + + fn enter_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { + self.arrow_function_converter.enter_function_body(body, ctx); + } + + fn exit_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { + self.arrow_function_converter.exit_function_body(body, ctx); + } + fn enter_static_block(&mut self, block: &mut StaticBlock<'a>, ctx: &mut TraverseCtx<'a>) { self.arrow_function_converter.enter_static_block(block, ctx); } diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 1ff1d32c6620e5..72aa494b504e16 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -171,6 +171,7 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> { arrow: &mut ArrowFunctionExpression<'a>, ctx: &mut TraverseCtx<'a>, ) { + self.common.enter_arrow_function_expression(arrow, ctx); if let Some(typescript) = self.x0_typescript.as_mut() { typescript.enter_arrow_function_expression(arrow, ctx); } @@ -314,6 +315,14 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> { self.common.exit_function(func, ctx); } + fn enter_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { + self.common.enter_function_body(body, ctx); + } + + fn exit_function_body(&mut self, body: &mut FunctionBody<'a>, ctx: &mut TraverseCtx<'a>) { + self.common.exit_function_body(body, ctx); + } + fn enter_jsx_element(&mut self, node: &mut JSXElement<'a>, ctx: &mut TraverseCtx<'a>) { if let Some(typescript) = self.x0_typescript.as_mut() { typescript.enter_jsx_element(node, ctx); From 44fd962fbbb384fe91da2cf92e18b880d854bc02 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Sun, 17 Nov 2024 10:49:17 +0000 Subject: [PATCH 025/121] perf(transformer/arrow-functions): move arguments transform checks to aid inlining (#7322) Move the cheap "does arguments need to be transformed" checks introduced in #7321 into `enter_identifier_reference` and `enter_binding_identifier`, and mark those methods `#[inline]`. These hot paths can then usually execute without a function call. This wins back the other half of the perf hit of #7234. --- .../src/common/arrow_function_converter.rs | 29 +++++++++++++------ 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index e1b80ff69c4c5e..46cfe3d7a6a4e4 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -368,20 +368,34 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { } } + // `#[inline]` because this is a hot path + #[inline] fn enter_identifier_reference( &mut self, ident: &mut IdentifierReference<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.transform_identifier_reference_for_arguments(ident, ctx); + // Do this check here rather than in `transform_identifier_reference_for_arguments` + // so that the fast path for "no transform required" doesn't require a function call + let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); + if arguments_needs_transform { + self.transform_identifier_reference_for_arguments(ident, ctx); + } } + // `#[inline]` because this is a hot path + #[inline] fn enter_binding_identifier( &mut self, ident: &mut BindingIdentifier<'a>, ctx: &mut TraverseCtx<'a>, ) { - self.transform_binding_identifier_for_arguments(ident, ctx); + // Do this check here rather than in `transform_binding_identifier_for_arguments` + // so that the fast path for "no transform required" doesn't require a function call + let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); + if arguments_needs_transform { + self.transform_binding_identifier_for_arguments(ident, ctx); + } } } @@ -907,8 +921,7 @@ impl<'a> ArrowFunctionConverter<'a> { ident: &mut IdentifierReference<'a>, ctx: &mut TraverseCtx<'a>, ) { - let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); - if !arguments_needs_transform || &ident.name != "arguments" { + if &ident.name != "arguments" { return; } @@ -952,11 +965,9 @@ impl<'a> ArrowFunctionConverter<'a> { ident: &mut BindingIdentifier<'a>, ctx: &mut TraverseCtx<'a>, ) { - let arguments_needs_transform = *self.arguments_needs_transform_stack.last(); - if !arguments_needs_transform - || ctx.current_scope_flags().is_strict_mode() // `arguments` is not allowed to be defined in strict mode - || &ident.name != "arguments" - { + // `arguments` is not allowed to be defined in strict mode. + // Check if strict mode first to avoid the more expensive string comparison check if possible. + if ctx.current_scope_flags().is_strict_mode() || &ident.name != "arguments" { return; } From 1938a1d6d94c5c3d401340d78457f27f6d57f346 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 18 Nov 2024 02:28:38 +0000 Subject: [PATCH 026/121] refactor(isolated_declarations): do not copy `Vec` unnecessarily (#7332) This function receives an owned `oxc_allocator::Vec`. No need to copy the contents to a new `Vec` with `AstBuilder::vec_from_iter`, can just use the original. --- crates/oxc_isolated_declarations/src/declaration.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/crates/oxc_isolated_declarations/src/declaration.rs b/crates/oxc_isolated_declarations/src/declaration.rs index c5ef8fcb842c84..701e1b5da15a2e 100644 --- a/crates/oxc_isolated_declarations/src/declaration.rs +++ b/crates/oxc_isolated_declarations/src/declaration.rs @@ -41,12 +41,7 @@ impl<'a> IsolatedDeclarations<'a> { decl: &VariableDeclaration<'a>, declarations: oxc_allocator::Vec<'a, VariableDeclarator<'a>>, ) -> Box<'a, VariableDeclaration<'a>> { - self.ast.alloc_variable_declaration( - decl.span, - decl.kind, - self.ast.vec_from_iter(declarations), - self.is_declare(), - ) + self.ast.alloc_variable_declaration(decl.span, decl.kind, declarations, self.is_declare()) } pub(crate) fn transform_variable_declarator( From 39afb48025a071faebc0d324079e9f8ba60b61ba Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 18 Nov 2024 02:35:46 +0000 Subject: [PATCH 027/121] feat(allocator): introduce `Vec::from_array_in` (#7331) Because we lack specialization in stable Rust, `Vec::from_iter_in` is unable to take advantage of the fact that `[T; N]` has a statically knowable size. Introduce `Vec::from_array_in` for this case, which should be able to create the `Vec` with a single static-sized memcpy, or may allow the compiler to see that it can construct the array directly in the arena, rather than construct on stack and then copy to the arena. Also add a corresponding `AstBuilder::vec_from_array` method, and use it in various places in codebase. --- crates/oxc_allocator/src/boxed.rs | 7 +++++ crates/oxc_allocator/src/vec.rs | 28 +++++++++++++++++++ crates/oxc_ast/src/ast_builder_impl.rs | 10 +++++++ .../oxc_isolated_declarations/src/function.rs | 2 +- .../src/return_type.rs | 2 +- .../src/ast_passes/peephole_fold_constants.rs | 6 ++-- .../src/es2016/exponentiation_operator.rs | 2 +- 7 files changed, 50 insertions(+), 7 deletions(-) diff --git a/crates/oxc_allocator/src/boxed.rs b/crates/oxc_allocator/src/boxed.rs index 3271631cb1c121..a91e7337f5160c 100644 --- a/crates/oxc_allocator/src/boxed.rs +++ b/crates/oxc_allocator/src/boxed.rs @@ -99,6 +99,13 @@ impl<'alloc, T: ?Sized> Box<'alloc, T> { pub(crate) const unsafe fn from_non_null(ptr: NonNull) -> Self { Self(ptr, PhantomData) } + + /// Consume a [`Box`] and return a [`NonNull`] pointer to its contents. + #[inline] + #[expect(clippy::needless_pass_by_value)] + pub fn into_non_null(boxed: Self) -> NonNull { + boxed.0 + } } impl<'alloc, T: ?Sized> ops::Deref for Box<'alloc, T> { diff --git a/crates/oxc_allocator/src/vec.rs b/crates/oxc_allocator/src/vec.rs index 471e47e47fc1c3..057333aae5c36c 100644 --- a/crates/oxc_allocator/src/vec.rs +++ b/crates/oxc_allocator/src/vec.rs @@ -117,6 +117,34 @@ impl<'alloc, T> Vec<'alloc, T> { Self(vec) } + /// Create a new [`Vec`] from a fixed-size array, allocated in the given `allocator`. + /// + /// This is preferable to `from_iter_in` where source is an array, as size is statically known, + /// and compiler is more likely to construct the values directly in arena, rather than constructing + /// on stack and then copying to arena. + /// + /// # Examples + /// + /// ``` + /// use oxc_allocator::{Allocator, Vec}; + /// + /// let allocator = Allocator::default(); + /// + /// let array: [u32; 4] = [1, 2, 3, 4]; + /// let vec = Vec::from_array_in(array, &allocator); + /// ``` + #[inline] + pub fn from_array_in(array: [T; N], allocator: &'alloc Allocator) -> Self { + let boxed = Box::new_in(array, allocator); + let ptr = Box::into_non_null(boxed).as_ptr().cast::(); + // SAFETY: `ptr` has correct alignment - it was just allocated as `[T; N]`. + // `ptr` was allocated with correct size for `[T; N]`. + // `len` and `capacity` are both `N`. + // Allocated size cannot be larger than `isize::MAX`, or `Box::new_in` would have failed. + let vec = unsafe { vec::Vec::from_raw_parts_in(ptr, N, N, &**allocator) }; + Self(ManuallyDrop::new(vec)) + } + /// Converts the vector into [`Box<[T]>`][owned slice]. /// /// Any excess capacity the vector has will not be included in the slice. diff --git a/crates/oxc_ast/src/ast_builder_impl.rs b/crates/oxc_ast/src/ast_builder_impl.rs index 9c5c4ccea58b06..80937d8333c7db 100644 --- a/crates/oxc_ast/src/ast_builder_impl.rs +++ b/crates/oxc_ast/src/ast_builder_impl.rs @@ -67,6 +67,16 @@ impl<'a> AstBuilder<'a> { Vec::from_iter_in(iter, self.allocator) } + /// Create [`Vec`] from a fixed-size array. + /// + /// This is preferable to `vec_from_iter` where source is an array, as size is statically known, + /// and compiler is more likely to construct the values directly in arena, rather than constructing + /// on stack and then copying to arena. + #[inline] + pub fn vec_from_array(self, array: [T; N]) -> Vec<'a, T> { + Vec::from_array_in(array, self.allocator) + } + /// Move a string slice into the memory arena, returning a reference to the slice /// in the heap. #[inline] diff --git a/crates/oxc_isolated_declarations/src/function.rs b/crates/oxc_isolated_declarations/src/function.rs index bfcf00beced15f..380098817f38d9 100644 --- a/crates/oxc_isolated_declarations/src/function.rs +++ b/crates/oxc_isolated_declarations/src/function.rs @@ -99,7 +99,7 @@ impl<'a> IsolatedDeclarations<'a> { SPAN, self.ast.ts_type_union_type( SPAN, - self.ast.vec_from_iter([ + self.ast.vec_from_array([ ts_type, self.ast.ts_type_undefined_keyword(SPAN), ]), diff --git a/crates/oxc_isolated_declarations/src/return_type.rs b/crates/oxc_isolated_declarations/src/return_type.rs index e785245fb7fd45..55a6ca51543830 100644 --- a/crates/oxc_isolated_declarations/src/return_type.rs +++ b/crates/oxc_isolated_declarations/src/return_type.rs @@ -113,7 +113,7 @@ impl<'a> FunctionReturnType<'a> { let types = transformer .ast - .vec_from_iter([expr_type, transformer.ast.ts_type_undefined_keyword(SPAN)]); + .vec_from_array([expr_type, transformer.ast.ts_type_undefined_keyword(SPAN)]); expr_type = transformer.ast.ts_type_union_type(SPAN, types); } Some(expr_type) diff --git a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs index 282ddbe102f835..2a547f25d4d791 100644 --- a/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs +++ b/crates/oxc_minifier/src/ast_passes/peephole_fold_constants.rs @@ -156,9 +156,7 @@ impl<'a, 'b> PeepholeFoldConstants { // or: false_with_sideeffects && foo() => false_with_sideeffects, foo() let left = ctx.ast.move_expression(&mut logical_expr.left); let right = ctx.ast.move_expression(&mut logical_expr.right); - let mut vec = ctx.ast.vec_with_capacity(2); - vec.push(left); - vec.push(right); + let vec = ctx.ast.vec_from_array([left, right]); let sequence_expr = ctx.ast.expression_sequence(logical_expr.span, vec); return Some(sequence_expr); } else if let Expression::LogicalExpression(left_child) = &mut logical_expr.left { @@ -201,7 +199,7 @@ impl<'a, 'b> PeepholeFoldConstants { ValueType::Null | ValueType::Undefined => { Some(if left.may_have_side_effects() { // e.g. `(a(), null) ?? 1` => `(a(), null, 1)` - let expressions = ctx.ast.vec_from_iter([ + let expressions = ctx.ast.vec_from_array([ ctx.ast.move_expression(&mut logical_expr.left), ctx.ast.move_expression(&mut logical_expr.right), ]); diff --git a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs index 38254c188783dd..ea9c73caa44c84 100644 --- a/crates/oxc_transformer/src/es2016/exponentiation_operator.rs +++ b/crates/oxc_transformer/src/es2016/exponentiation_operator.rs @@ -545,7 +545,7 @@ impl<'a, 'ctx> ExponentiationOperator<'a, 'ctx> { let property = ctx.ast.identifier_name(SPAN, "pow"); let callee = Expression::from(ctx.ast.member_expression_static(SPAN, object, property, false)); - let arguments = ctx.ast.vec_from_iter([Argument::from(left), Argument::from(right)]); + let arguments = ctx.ast.vec_from_array([Argument::from(left), Argument::from(right)]); ctx.ast.expression_call(SPAN, callee, NONE, arguments, false) } From 510b95d6c4c5d5a685a28bf62345a1dbe30107a3 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 18 Nov 2024 02:35:46 +0000 Subject: [PATCH 028/121] perf(transformer): use `AstBuilder::vec_from_array` (#7333) Use `AstBuilder::vec_from_array` introduced in #7331 in the transformer, in place of creating a `Vec` with `Vec::with_capacity` and then pushing values to it. --- .../src/es2017/async_to_generator.rs | 44 +++++++++---------- .../async_generator_functions/for_await.rs | 28 +++++------- crates/oxc_transformer/src/jsx/jsx_source.rs | 5 +-- crates/oxc_transformer/src/jsx/refresh.rs | 11 ++--- crates/oxc_transformer/src/regexp/mod.rs | 10 ++--- .../src/typescript/namespace.rs | 8 ++-- 6 files changed, 46 insertions(+), 60 deletions(-) diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index 9e8729f59fe8a3..dfadcd01e53c9b 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -297,16 +297,14 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { { // Modify the wrapper function to add new body, params, and scope_id. - let mut statements = ctx.ast.vec_with_capacity(3); - let statement = self.create_async_to_generator_declaration( + let async_to_gen_decl = self.create_async_to_generator_declaration( &bound_ident, params, body, generator_scope_id, ctx, ); - statements.push(statement); - if has_function_id { + let statements = if has_function_id { let id = caller_function.id.as_ref().unwrap(); // If the function has an id, then we need to return the id. // `function foo() { ... }` -> `function foo() {} return foo;` @@ -316,17 +314,17 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { id.symbol_id(), ReferenceFlags::Read, ); - let statement = Statement::FunctionDeclaration(caller_function); - statements.push(statement); - statements.push(ctx.ast.statement_return(SPAN, Some(reference))); + let func_decl = Statement::FunctionDeclaration(caller_function); + let statement_return = ctx.ast.statement_return(SPAN, Some(reference)); + ctx.ast.vec_from_array([async_to_gen_decl, func_decl, statement_return]) } else { // If the function doesn't have an id, then we need to return the function itself. // `function() { ... }` -> `return function() { ... };` let statement_return = ctx .ast .statement_return(SPAN, Some(Expression::FunctionExpression(caller_function))); - statements.push(statement_return); - } + ctx.ast.vec_from_array([async_to_gen_decl, statement_return]) + }; debug_assert!(wrapper_function.body.is_none()); wrapper_function.r#async = false; wrapper_function.generator = false; @@ -382,15 +380,16 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { // function _name() { _ref.apply(this, arguments); } { - let mut statements = ctx.ast.vec_with_capacity(2); - statements.push(self.create_async_to_generator_assignment( - &bound_ident, - params, - body, - generator_scope_id, - ctx, - )); - statements.push(Self::create_apply_call_statement(&bound_ident, ctx)); + let statements = ctx.ast.vec_from_array([ + self.create_async_to_generator_assignment( + &bound_ident, + params, + body, + generator_scope_id, + ctx, + ), + Self::create_apply_call_statement(&bound_ident, ctx), + ]); let body = ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), statements); let scope_id = ctx.create_child_scope(ctx.current_scope_id(), ScopeFlags::Function); @@ -468,9 +467,7 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { generator_function_id, ctx, ); - let mut statements = ctx.ast.vec_with_capacity(2); - statements.push(statement); - statements.push(caller_function); + let statements = ctx.ast.vec_from_array([statement, caller_function]); let body = ctx.ast.alloc_function_body(SPAN, ctx.ast.vec(), statements); let params = Self::create_empty_params(ctx); let wrapper_function = Self::create_function(None, params, body, wrapper_scope_id, ctx); @@ -604,9 +601,8 @@ impl<'a, 'ctx> AsyncGeneratorExecutor<'a, 'ctx> { )); // (this, arguments) - let mut arguments = ctx.ast.vec_with_capacity(2); - arguments.push(Argument::from(ctx.ast.expression_this(SPAN))); - arguments.push(arguments_ident); + let this = Argument::from(ctx.ast.expression_this(SPAN)); + let arguments = ctx.ast.vec_from_array([this, arguments_ident]); // _ref.apply let callee = Expression::from(ctx.ast.member_expression_static( SPAN, diff --git a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs index 7e006971401610..d57ecf556fba10 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/for_await.rs @@ -261,24 +261,22 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { Some(ctx.ast.for_statement_init_variable_declaration( SPAN, VariableDeclarationKind::Var, - { - let mut items = ctx.ast.vec_with_capacity(2); - items.push(ctx.ast.variable_declarator( + ctx.ast.vec_from_array([ + ctx.ast.variable_declarator( SPAN, VariableDeclarationKind::Var, iterator_key.create_binding_pattern(ctx), Some(iterator), false, - )); - items.push(ctx.ast.variable_declarator( + ), + ctx.ast.variable_declarator( SPAN, VariableDeclarationKind::Var, step_key.create_binding_pattern(ctx), None, false, - )); - items - }, + ), + ]), false, )), Some(ctx.ast.expression_assignment( @@ -371,9 +369,8 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { { ctx.ast.block_statement_with_scope_id( SPAN, - { - let mut items = ctx.ast.vec_with_capacity(2); - items.push(ctx.ast.statement_expression( + ctx.ast.vec_from_array([ + ctx.ast.statement_expression( SPAN, ctx.ast.expression_assignment( SPAN, @@ -381,8 +378,8 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { iterator_had_error_key.create_write_target(ctx), ctx.ast.expression_boolean_literal(SPAN, true), ), - )); - items.push(ctx.ast.statement_expression( + ), + ctx.ast.statement_expression( SPAN, ctx.ast.expression_assignment( SPAN, @@ -390,9 +387,8 @@ impl<'a, 'ctx> AsyncGeneratorFunctions<'a, 'ctx> { iterator_error_key.create_write_target(ctx), err_ident.create_read_expression(ctx), ), - )); - items - }, + ), + ]), block_scope_id, ) }, diff --git a/crates/oxc_transformer/src/jsx/jsx_source.rs b/crates/oxc_transformer/src/jsx/jsx_source.rs index 232cc4fba99ee6..c0a1eae289f9be 100644 --- a/crates/oxc_transformer/src/jsx/jsx_source.rs +++ b/crates/oxc_transformer/src/jsx/jsx_source.rs @@ -176,10 +176,7 @@ impl<'a, 'ctx> JsxSource<'a, 'ctx> { .object_property_kind_object_property(SPAN, kind, key, value, false, false, false) }; - let mut properties = ctx.ast.vec_with_capacity(3); - properties.push(filename); - properties.push(line_number); - properties.push(column_number); + let properties = ctx.ast.vec_from_array([filename, line_number, column_number]); ctx.ast.expression_object(SPAN, properties, None) } diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index a7145f0d06660f..f55dc2b4b90b05 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -164,11 +164,12 @@ impl<'a, 'ctx> Traverse<'a> for ReactRefresh<'a, 'ctx> { )); let callee = self.refresh_reg.to_expression(ctx); - let mut arguments = ctx.ast.vec_with_capacity(2); - arguments.push(Argument::from(binding.create_read_expression(ctx))); - arguments.push(Argument::from( - ctx.ast.expression_string_literal(SPAN, ctx.ast.atom(&persistent_id)), - )); + let arguments = ctx.ast.vec_from_array([ + Argument::from(binding.create_read_expression(ctx)), + Argument::from( + ctx.ast.expression_string_literal(SPAN, ctx.ast.atom(&persistent_id)), + ), + ]); new_statements.push(ctx.ast.statement_expression( SPAN, ctx.ast.expression_call(SPAN, callee, NONE, arguments, false), diff --git a/crates/oxc_transformer/src/regexp/mod.rs b/crates/oxc_transformer/src/regexp/mod.rs index fdb69fdb00746c..14097852ffa485 100644 --- a/crates/oxc_transformer/src/regexp/mod.rs +++ b/crates/oxc_transformer/src/regexp/mod.rs @@ -183,12 +183,10 @@ impl<'a, 'ctx> Traverse<'a> for RegExp<'a, 'ctx> { ctx.create_ident_expr(SPAN, Atom::from("RegExp"), symbol_id, ReferenceFlags::read()) }; - let mut arguments = ctx.ast.vec_with_capacity(2); - arguments.push(Argument::from(ctx.ast.expression_string_literal(SPAN, pattern_source))); - - let flags_str = flags.to_string(); - let flags_str = Argument::from(ctx.ast.expression_string_literal(SPAN, flags_str)); - arguments.push(flags_str); + let arguments = ctx.ast.vec_from_array([ + Argument::from(ctx.ast.expression_string_literal(SPAN, pattern_source)), + Argument::from(ctx.ast.expression_string_literal(SPAN, flags.to_string())), + ]); *expr = ctx.ast.expression_new(regexp.span, callee, arguments, NONE); } diff --git a/crates/oxc_transformer/src/typescript/namespace.rs b/crates/oxc_transformer/src/typescript/namespace.rs index a5e96496d33726..581732f1007cb3 100644 --- a/crates/oxc_transformer/src/typescript/namespace.rs +++ b/crates/oxc_transformer/src/typescript/namespace.rs @@ -491,12 +491,10 @@ impl<'a, 'ctx> TypeScriptNamespace<'a, 'ctx> { assignments.push(Self::create_assignment_statement(name.clone(), id.name.clone(), ctx)); }); - let mut stmts = ctx.ast.vec_with_capacity(2); - stmts.push(Statement::VariableDeclaration(var_decl)); - stmts.push( + ctx.ast.vec_from_array([ + Statement::VariableDeclaration(var_decl), ctx.ast.statement_expression(SPAN, ctx.ast.expression_sequence(SPAN, assignments)), - ); - stmts + ]) } } From c84e892380d321983e18234803e39ae1c4e33f98 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 18 Nov 2024 02:35:46 +0000 Subject: [PATCH 029/121] perf(ast): `AstBuilder::vec1` use `Vec::from_array_in` (#7334) `AstBuilder::vec1` can use `Vec::from_array_in` rather than creating a `Vec` and then pushing to it. This should optimize better. --- crates/oxc_ast/src/ast_builder_impl.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/crates/oxc_ast/src/ast_builder_impl.rs b/crates/oxc_ast/src/ast_builder_impl.rs index 80937d8333c7db..80aeb1087ba954 100644 --- a/crates/oxc_ast/src/ast_builder_impl.rs +++ b/crates/oxc_ast/src/ast_builder_impl.rs @@ -56,9 +56,7 @@ impl<'a> AstBuilder<'a> { /// Create a new arena-allocated [`Vec`] initialized with a single element. #[inline] pub fn vec1(self, value: T) -> Vec<'a, T> { - let mut vec = self.vec_with_capacity(1); - vec.push(value); - vec + self.vec_from_array([value]) } /// Collect an iterator into a new arena-allocated [`Vec`]. From 7b83a3ddfa835445a9727d63de3f43cb1a4a98bd Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 18 Nov 2024 18:01:49 +0800 Subject: [PATCH 030/121] chore(tasks/coverage): update runtime.snap --- tasks/coverage/snapshots/runtime.snap | 173 +------------------------- 1 file changed, 1 insertion(+), 172 deletions(-) diff --git a/tasks/coverage/snapshots/runtime.snap b/tasks/coverage/snapshots/runtime.snap index fdf09af2d9d362..127d0c86e05b60 100644 --- a/tasks/coverage/snapshots/runtime.snap +++ b/tasks/coverage/snapshots/runtime.snap @@ -2,142 +2,7 @@ commit: 06454619 runtime Summary: AST Parsed : 18055/18055 (100.00%) -Positive Passed: 17798/18055 (98.58%) -tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/async-gen-meth-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-static-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-static-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-static-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-static-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-gen-meth-static-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-static-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-static-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-static-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-static-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-decl-async-private-gen-meth-static-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-static-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-static-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-static-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-static-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-gen-meth-static-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-static-args-trailing-comma-multiple.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-static-args-trailing-comma-null.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-static-args-trailing-comma-single-args.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-static-args-trailing-comma-spread-operator.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«4Β») to be true - -tasks/coverage/test262/test/language/arguments-object/cls-expr-async-private-gen-meth-static-args-trailing-comma-undefined.js -transform error: Test262Error: Expected SameValue(Β«0Β», Β«2Β») to be true - +Positive Passed: 17855/18055 (98.89%) tasks/coverage/test262/test/language/expressions/assignment/fn-name-lhs-cover.js codegen error: Test262Error: descriptor value should be ; object value should be @@ -177,9 +42,6 @@ transform error: Test262Error: Expected SameValue(Β«1Β», Β«function BindingIdent return _BindingIdentifier.apply(this, arguments); }Β») to be true -tasks/coverage/test262/test/language/expressions/async-function/named-returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/async-function/named-strict-error-reassign-fn-name-in-body-in-arrow.js transform error: Test262Error: Expected SameValue(Β«0Β», Β«1Β») to be true @@ -360,9 +222,6 @@ transform error: ReferenceError: Cannot access 'y' before initialization tasks/coverage/test262/test/language/expressions/class/async-method/dflt-params-ref-self.js transform error: ReferenceError: Cannot access 'x' before initialization -tasks/coverage/test262/test/language/expressions/class/async-method/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/class/async-method-static/dflt-params-abrupt.js transform error: Test262Error: @@ -372,9 +231,6 @@ transform error: ReferenceError: Cannot access 'y' before initialization tasks/coverage/test262/test/language/expressions/class/async-method-static/dflt-params-ref-self.js transform error: ReferenceError: Cannot access 'x' before initialization -tasks/coverage/test262/test/language/expressions/class/async-method-static/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/class/elements/async-gen-private-method/yield-star-async-next.js transform error: Test262Error: Expected SameValue(Β«"get next done (1)"Β», Β«"get next value (1)"Β») to be true @@ -435,12 +291,6 @@ transform error: Test262Error: reject reason Expected SameValue(Β«TypeError: The tasks/coverage/test262/test/language/expressions/class/elements/async-gen-private-method-static/yield-star-sync-throw.js transform error: throw-arg-1 -tasks/coverage/test262/test/language/expressions/class/elements/async-private-method/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - -tasks/coverage/test262/test/language/expressions/class/elements/async-private-method-static/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/class/heritage-arrow-function.js transform error: Test262Error: Expected a TypeError to be thrown but no exception was thrown at all @@ -495,9 +345,6 @@ transform error: ReferenceError: Cannot access 'x' before initialization tasks/coverage/test262/test/language/expressions/object/method-definition/async-meth-eval-var-scope-syntax-err.js transform error: SyntaxError: Identifier 'a' has already been declared -tasks/coverage/test262/test/language/expressions/object/method-definition/async-returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/expressions/object/method-definition/async-super-call-param.js transform error: ReferenceError: _superprop_getMethod is not defined @@ -510,9 +357,6 @@ transform error: Test262Error: Expected SameValue(Β«trueΒ», Β«falseΒ») to be tru tasks/coverage/test262/test/language/statements/async-function/forbidden-ext/b1/async-func-decl-forbidden-ext-direct-access-prop-caller.js transform error: Test262Error: Expected SameValue(Β«trueΒ», Β«falseΒ») to be true -tasks/coverage/test262/test/language/statements/async-function/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/statements/async-generator/forbidden-ext/b1/async-gen-func-decl-forbidden-ext-direct-access-prop-arguments.js transform error: Test262Error: Expected SameValue(Β«trueΒ», Β«falseΒ») to be true @@ -639,9 +483,6 @@ transform error: ReferenceError: Cannot access 'y' before initialization tasks/coverage/test262/test/language/statements/class/async-method/dflt-params-ref-self.js transform error: ReferenceError: Cannot access 'x' before initialization -tasks/coverage/test262/test/language/statements/class/async-method/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/statements/class/async-method-static/dflt-params-abrupt.js transform error: Test262Error: @@ -651,9 +492,6 @@ transform error: ReferenceError: Cannot access 'y' before initialization tasks/coverage/test262/test/language/statements/class/async-method-static/dflt-params-ref-self.js transform error: ReferenceError: Cannot access 'x' before initialization -tasks/coverage/test262/test/language/statements/class/async-method-static/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - tasks/coverage/test262/test/language/statements/class/definition/methods-async-super-call-param.js transform error: ReferenceError: _superprop_getMethod is not defined @@ -717,15 +555,6 @@ transform error: Test262Error: reject reason Expected SameValue(Β«TypeError: The tasks/coverage/test262/test/language/statements/class/elements/async-gen-private-method-static/yield-star-sync-throw.js transform error: throw-arg-1 -tasks/coverage/test262/test/language/statements/class/elements/async-private-method/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - -tasks/coverage/test262/test/language/statements/class/elements/async-private-method-static/returns-async-arrow-returns-arguments-from-parent-function.js -transform error: Test262Error: Expected SameValue(Β«falseΒ», Β«trueΒ») to be true - -tasks/coverage/test262/test/language/statements/class/static-init-arguments-methods.js -transform error: Test262Error: Actual [async method] and expected [] should have the same contents. body - tasks/coverage/test262/test/language/statements/class/subclass/superclass-async-function.js transform error: TypeError: Cannot redefine property: prototype From 167d2d560dfe1e33d0910a4ef54363f16f9f99ef Mon Sep 17 00:00:00 2001 From: leaysgur <6259812+leaysgur@users.noreply.github.com> Date: Mon, 18 Nov 2024 11:54:33 +0000 Subject: [PATCH 031/121] chore(docs): Replace TAB with SPACE to render markdown correctly (#7337) Possibly fixes #7336 --- .../rules/react/jsx_curly_brace_presence.rs | 224 +++++++++--------- 1 file changed, 112 insertions(+), 112 deletions(-) diff --git a/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs b/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs index a03a2a6ff7cce3..eb13ed3295eaac 100644 --- a/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs +++ b/crates/oxc_linter/src/rules/react/jsx_curly_brace_presence.rs @@ -84,7 +84,7 @@ declare_oxc_lint!( /// sufficient or enforce JSX expressions on literals in JSX children or /// attributes (`react/jsx-curly-brace-presence`) /// - /// πŸ”§ This rule is automatically fixable by the [`--fix` CLI option](https://oxc-project.github.io/docs/guide/usage/linter/cli.html#fix-problems). + /// πŸ”§ This rule is automatically fixable by the [`--fix` CLI option](https://oxc-project.github.io/docs/guide/usage/linter/cli.html#fix-problems). /// /// This rule allows you to enforce curly braces or disallow unnecessary /// curly braces in JSX props and/or children. @@ -94,7 +94,7 @@ declare_oxc_lint!( /// and [this page about JSX /// gotchas](https://github.com/facebook/react/blob/v15.4.0-rc.3/docs/docs/02.3-jsx-gotchas.md#html-entities). /// - /// ## Rule Details + /// ## Rule Details /// /// By default, this rule will check for and warn about unnecessary curly /// braces in both JSX props and children. For the sake of backwards @@ -111,128 +111,128 @@ declare_oxc_lint!( /// to omit curly braces around prop values that are JSX elements is /// obscure, and intentionally undocumented, and should not be relied upon. /// - /// ## Rule Options + /// ## Rule Options /// - /// ```js - /// ... - /// "react/jsx-curly-brace-presence": [, { "props": , "children": , "propElementValues": }] - /// ... - /// ``` + /// ```js + /// ... + /// "react/jsx-curly-brace-presence": [, { "props": , "children": , "propElementValues": }] + /// ... + /// ``` /// - /// or alternatively + /// or alternatively /// - /// ```js - /// ... - /// "react/jsx-curly-brace-presence": [, ] - /// ... - /// ``` + /// ```js + /// ... + /// "react/jsx-curly-brace-presence": [, ] + /// ... + /// ``` /// - /// ### Valid options for `` + /// ### Valid options for `` /// /// They are `always`, `never` and `ignore` for checking on JSX props and /// children. /// - /// - `always`: always enforce curly braces inside JSX props, children, and/or JSX prop values that are JSX Elements - /// - `never`: never allow unnecessary curly braces inside JSX props, children, and/or JSX prop values that are JSX Elements - /// - `ignore`: ignore the rule for JSX props, children, and/or JSX prop values that are JSX Elements + /// - `always`: always enforce curly braces inside JSX props, children, and/or JSX prop values that are JSX Elements + /// - `never`: never allow unnecessary curly braces inside JSX props, children, and/or JSX prop values that are JSX Elements + /// - `ignore`: ignore the rule for JSX props, children, and/or JSX prop values that are JSX Elements /// - /// If passed in the option to fix, this is how a style violation will get fixed + /// If passed in the option to fix, this is how a style violation will get fixed /// - /// - `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes - /// - `never`: get rid of curly braces from a JSX attribute and/or a JSX child + /// - `always`: wrap a JSX attribute in curly braces/JSX expression and/or a JSX child the same way but also with double quotes + /// - `never`: get rid of curly braces from a JSX attribute and/or a JSX child /// - /// - All fixing operations use double quotes. + /// - All fixing operations use double quotes. /// - /// For examples: + /// For examples: /// - /// Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always" }`: + /// Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always" }`: /// - /// ```jsx - /// Hello world; - /// {'Hello world'}; - /// ``` + /// ```jsx + /// Hello world; + /// {'Hello world'}; + /// ``` /// - /// They can be fixed to: + /// They can be fixed to: /// - /// ```jsx - /// {"Hello world"}; - /// {'Hello world'}; - /// ``` + /// ```jsx + /// {"Hello world"}; + /// {'Hello world'}; + /// ``` /// - /// Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never" }`: + /// Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never" }`: /// - /// ```jsx - /// {'Hello world'}; - /// ; - /// ``` + /// ```jsx + /// {'Hello world'}; + /// ; + /// ``` /// - /// They can be fixed to: + /// They can be fixed to: /// - /// ```jsx - /// Hello world; - /// ; - /// ``` + /// ```jsx + /// Hello world; + /// ; + /// ``` /// - /// Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always", "propElementValues": "always" }`: + /// Examples of **incorrect** code for this rule, when configured with `{ props: "always", children: "always", "propElementValues": "always" }`: /// - /// ```jsx - /// />; - /// ``` + /// ```jsx + /// />; + /// ``` /// - /// They can be fixed to: + /// They can be fixed to: /// - /// ```jsx - /// } />; - /// ``` + /// ```jsx + /// } />; + /// ``` /// - /// Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never", "propElementValues": "never" }`: + /// Examples of **incorrect** code for this rule, when configured with `{ props: "never", children: "never", "propElementValues": "never" }`: /// - /// ```jsx - /// } />; - /// ``` + /// ```jsx + /// } />; + /// ``` /// - /// They can be fixed to: + /// They can be fixed to: /// - /// ```jsx - /// />; - /// ``` + /// ```jsx + /// />; + /// ``` /// - /// ### Alternative syntax + /// ### Alternative syntax /// - /// The options are also `always`, `never`, and `ignore` for the same meanings. + /// The options are also `always`, `never`, and `ignore` for the same meanings. /// /// In this syntax, only a string is provided and the default will be set to /// that option for checking on both JSX props and children. /// - /// For examples: + /// For examples: /// - /// Examples of **incorrect** code for this rule, when configured with `"always"`: + /// Examples of **incorrect** code for this rule, when configured with `"always"`: /// - /// ```jsx - /// Hello world; - /// Hello world; - /// ``` + /// ```jsx + /// Hello world; + /// Hello world; + /// ``` /// - /// They can be fixed to: + /// They can be fixed to: /// - /// ```jsx - /// {"Hello world"}; - /// {"Hello world"}; - /// ``` + /// ```jsx + /// {"Hello world"}; + /// {"Hello world"}; + /// ``` /// - /// Examples of **incorrect** code for this rule, when configured with `"never"`: + /// Examples of **incorrect** code for this rule, when configured with `"never"`: /// - /// ```jsx - /// {'Hello world'}; - /// ``` + /// ```jsx + /// {'Hello world'}; + /// ``` /// - /// It can fixed to: + /// It can fixed to: /// - /// ```jsx - /// Hello world; - /// ``` + /// ```jsx + /// Hello world; + /// ``` /// - /// ## Edge cases + /// ## Edge cases /// /// The fix also deals with template literals, strings with quotes, and /// strings with escapes characters. @@ -241,32 +241,32 @@ declare_oxc_lint!( /// template literal inside a JSX expression has no expression, it will /// throw a warning and be fixed with double quotes. For example: /// - /// ```jsx - /// {`Hello world`}; - /// ``` + /// ```jsx + /// {`Hello world`}; + /// ``` /// - /// will be warned and fixed to: + /// will be warned and fixed to: /// - /// ```jsx - /// Hello world; - /// ``` + /// ```jsx + /// Hello world; + /// ``` /// /// - If the rule is set to enforce curly braces and the strings have /// quotes, it will be fixed with double quotes for JSX children and the /// normal way for JSX attributes. Also, double quotes will be escaped in /// the fix. /// - /// For example: + /// For example: /// - /// ```jsx - /// Hello 'foo' "bar" world; - /// ``` + /// ```jsx + /// Hello 'foo' "bar" world; + /// ``` /// - /// will warned and fixed to: + /// will warned and fixed to: /// - /// ```jsx - /// {"Hello 'foo' \"bar\" world"}; - /// ``` + /// ```jsx + /// {"Hello 'foo' \"bar\" world"}; + /// ``` /// /// - If the rule is set to get rid of unnecessary curly braces(JSX /// expression) and there are characters that need to be escaped in its JSX @@ -275,22 +275,22 @@ declare_oxc_lint!( /// anything that looks like HTML entity names, the code will not be warned /// because the fix may make the code less readable. /// - /// Examples of **correct** code for this rule, even when configured with `"never"`: - /// - /// ```jsx - /// - /// {"Hello \u00b7 world"}; - /// ; - /// /** - /// * there's no way to inject a whitespace into jsx without a container so this - /// * will always be allowed. - /// */ - /// {' '} - /// {' '} - /// {/* comment */ } // the comment makes the container necessary - /// ``` - /// - /// ## When Not To Use It + /// Examples of **correct** code for this rule, even when configured with `"never"`: + /// + /// ```jsx + /// + /// {"Hello \u00b7 world"}; + /// ; + /// /** + /// * there's no way to inject a whitespace into jsx without a container so this + /// * will always be allowed. + /// */ + /// {' '} + /// {' '} + /// {/* comment */ } // the comment makes the container necessary + /// ``` + /// + /// ## When Not To Use It /// /// You should turn this rule off if you are not concerned about maintaining /// consistency regarding the use of curly braces in JSX props and/or From bf839c1dfa1dcf6a48ec1fcadf49a1fe839e6f06 Mon Sep 17 00:00:00 2001 From: dalaoshu Date: Mon, 18 Nov 2024 23:17:36 +0800 Subject: [PATCH 032/121] fix(linter): false positive in `jest/expect-expect` (#7341) closes #7237 --- .../src/rules/jest/expect_expect.rs | 75 ++++++++++--------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/crates/oxc_linter/src/rules/jest/expect_expect.rs b/crates/oxc_linter/src/rules/jest/expect_expect.rs index c95e72c1fffd79..2d283329b314e1 100644 --- a/crates/oxc_linter/src/rules/jest/expect_expect.rs +++ b/crates/oxc_linter/src/rules/jest/expect_expect.rs @@ -248,16 +248,21 @@ fn check_statements<'a>( visited: &mut FxHashSet, ctx: &LintContext<'a>, ) -> bool { - statements.iter().any(|statement| { - if let Statement::ExpressionStatement(expr_stmt) = statement { - return check_assert_function_used( - &expr_stmt.expression, - assert_function_names, - visited, - ctx, - ); + statements.iter().any(|statement| match statement { + Statement::ExpressionStatement(expr_stmt) => { + check_assert_function_used(&expr_stmt.expression, assert_function_names, visited, ctx) } - false + Statement::BlockStatement(block_stmt) => { + check_statements(&block_stmt.body, assert_function_names, visited, ctx) + } + Statement::IfStatement(if_stmt) => { + if let Statement::BlockStatement(block_stmt) = &if_stmt.consequent { + check_statements(&block_stmt.body, assert_function_names, visited, ctx) + } else { + false + } + } + _ => false, }) } @@ -287,32 +292,6 @@ fn convert_pattern(pattern: &str) -> CompactStr { format!("(?ui)^{pattern}(\\.|$)").into() } -#[test] -fn debug() { - use crate::tester::Tester; - - let mut pass: Vec<(&str, Option)> = vec![]; - - let mut fail = vec![]; - - let pass_vitest = vec![( - " - import { test } from 'vitest'; - test.skip(\"skipped test\", () => {}) - ", - None, - )]; - - let fail_vitest = vec![]; - - pass.extend(pass_vitest); - fail.extend(fail_vitest); - - Tester::new(ExpectExpect::NAME, pass, fail) - .with_jest_plugin(true) - .with_vitest_plugin(true) - .test(); -} #[test] fn test() { use crate::tester::Tester; @@ -438,6 +417,32 @@ fn test() { "#, None, ), + ( + r#" + it("should not warn on await expect", async () => { + if(true) { + const asyncFunction = async () => { + throw new Error('nope') + }; + await expect(asyncFunction()).rejects.toThrow(); + } + }); + "#, + None, + ), + ( + r#" + it("should not warn on await expect", async () => { + { + const asyncFunction = async () => { + throw new Error('nope') + }; + await expect(asyncFunction()).rejects.toThrow(); + } + }); + "#, + None, + ), ]; let mut fail = vec![ From b5a202711c7ddc5c6e331f259a7385c3559e47ce Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Mon, 18 Nov 2024 22:26:30 +0000 Subject: [PATCH 033/121] style(syntax): improve formatting (#7349) Style nit. Adjust formatting. --- crates/oxc_syntax/src/operator.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/crates/oxc_syntax/src/operator.rs b/crates/oxc_syntax/src/operator.rs index 9ccd9bab531565..1a0a5e0eecda80 100644 --- a/crates/oxc_syntax/src/operator.rs +++ b/crates/oxc_syntax/src/operator.rs @@ -78,16 +78,20 @@ impl AssignmentOperator { /// Returns `true` for `+=`, `-=`, `*=`, `/=`, `%=`, and `**=`. #[rustfmt::skip] pub fn is_arithmetic(self) -> bool { - matches!(self, Self::Addition | Self::Subtraction | Self::Multiplication - | Self::Division | Self::Remainder | Self::Exponential + matches!( + self, + Self::Addition | Self::Subtraction | Self::Multiplication + | Self::Division | Self::Remainder | Self::Exponential ) } /// Returns `true` for `|=`, `^=`, `&=`, `<<=`, `>>=`, and `>>>=`. #[rustfmt::skip] pub fn is_bitwise(self) -> bool { - matches!(self, Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd - | Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill + matches!( + self, + Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd + | Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill ) } @@ -209,8 +213,11 @@ impl BinaryOperator { /// Returns `true` for arithmetic operators #[rustfmt::skip] pub fn is_arithmetic(self) -> bool { - matches!(self, Self::Addition | Self::Subtraction | Self::Multiplication - | Self::Division | Self::Remainder | Self::Exponential) + matches!( + self, + Self::Addition | Self::Subtraction | Self::Multiplication + | Self::Division | Self::Remainder | Self::Exponential + ) } /// Returns `true` for multiplication (`*`), division (`/`), and remainder From 4b8aecc8ed2e005fd6d6e1af85caf9e91dc215e7 Mon Sep 17 00:00:00 2001 From: "Alexander S." Date: Tue, 19 Nov 2024 02:05:19 +0100 Subject: [PATCH 034/121] ci(editor): add lint and compile checks (#7346) --- .github/workflows/ci_vscode.yml | 47 +++++++++++++++++ editors/vscode/oxlint.json | 6 +++ editors/vscode/package.json | 4 +- pnpm-lock.yaml | 89 ++++++++++++++++++++++++++++++--- 4 files changed, 139 insertions(+), 7 deletions(-) create mode 100644 .github/workflows/ci_vscode.yml create mode 100644 editors/vscode/oxlint.json diff --git a/.github/workflows/ci_vscode.yml b/.github/workflows/ci_vscode.yml new file mode 100644 index 00000000000000..d2fb3fa86c76a9 --- /dev/null +++ b/.github/workflows/ci_vscode.yml @@ -0,0 +1,47 @@ +name: CI VSCode + +on: + workflow_dispatch: + pull_request: + types: [opened, synchronize] + paths: + - "pnpm-lock.yaml" + - "crates/oxc_language_server/**" + - "editors/vscode/**" + - ".github/worfkflows/ci_vscode.yml" + push: + branches: + - main + - "renovate/**" + paths: + - "pnpm-lock.yaml" + - "crates/oxc_language_server/**" + - "editors/vscode/**" + - ".github/worfkflows/ci_vscode.yml" + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }} + cancel-in-progress: ${{ github.ref_name != 'main' }} + +jobs: + compile: + name: Compile + runs-on: ubuntu-latest + steps: + - uses: taiki-e/checkout-action@v1 + - uses: ./.github/actions/pnpm + + - name: Compile VSCode + working-directory: editors/vscode + run: pnpm run compile + + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - uses: taiki-e/checkout-action@v1 + - uses: ./.github/actions/pnpm + + - name: Lint VSCode + working-directory: editors/vscode + run: pnpm run lint diff --git a/editors/vscode/oxlint.json b/editors/vscode/oxlint.json new file mode 100644 index 00000000000000..4b8c9578b7b394 --- /dev/null +++ b/editors/vscode/oxlint.json @@ -0,0 +1,6 @@ +{ + "categories": { + "correctness": "error", + "perf": "error" + } +} diff --git a/editors/vscode/package.json b/editors/vscode/package.json index ae7f70f04c774b..a6078cb3b223fb 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -135,7 +135,8 @@ "package": "vsce package --no-dependencies -o oxc_language_server.vsix", "install-extension": "code --install-extension oxc_language_server.vsix --force", "server:build:debug": "cargo build -p oxc_language_server", - "server:build:release": "cross-env CARGO_TARGET_DIR=./target cargo build -p oxc_language_server --release" + "server:build:release": "cross-env CARGO_TARGET_DIR=./target cargo build -p oxc_language_server --release", + "lint": "npx oxlint --config=oxlint.json --tsconfig=tsconfig.json" }, "devDependencies": { "@types/node": "^22.0.0", @@ -144,6 +145,7 @@ "cross-env": "^7.0.3", "esbuild": "^0.24.0", "ovsx": "^0.10.0", + "oxlint": "^0.11.1", "typescript": "^5.4.5" }, "dependencies": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fd68b5cdb5b1b2..d8b33d33269906 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -54,6 +54,9 @@ importers: ovsx: specifier: ^0.10.0 version: 0.10.0 + oxlint: + specifier: ^0.11.1 + version: 0.11.1 typescript: specifier: ^5.4.5 version: 5.6.3 @@ -78,12 +81,6 @@ importers: npm/oxc-types: {} - npm/oxc-wasm: - dependencies: - '@oxc-project/types': - specifier: workspace:^ - version: link:../oxc-types - npm/oxlint: {} npm/parser-wasm: @@ -888,6 +885,46 @@ packages: '@octokit/types@13.5.0': resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} + '@oxlint/darwin-arm64@0.11.1': + resolution: {integrity: sha512-S+cHn49fT+qSJXhQ3Z4EG/5ENp2dAUbS2sMNkhgkLqlO8aYl0TR9R7omU3vpU/beu8ePnV+mdVlJYGjsPIMGtg==} + cpu: [arm64] + os: [darwin] + + '@oxlint/darwin-x64@0.11.1': + resolution: {integrity: sha512-LPuF0D8uu30KIVEeVuGwIPwHwJRQ1i1otwFFH7tRsNXPgMgZJ4VgriyH22i6RWwBtclJoCSBLtGK6gLZ0oZBvw==} + cpu: [x64] + os: [darwin] + + '@oxlint/linux-arm64-gnu@0.11.1': + resolution: {integrity: sha512-CYBE+GRIPs5e+raD2pdicuBn6Y6E1xAnyWQ/kHE4GEWDAQZY0Um2VYEUTGH2ObwJ3uXr6jeJ16HOKJvr0S8a8w==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-arm64-musl@0.11.1': + resolution: {integrity: sha512-iYXF5N5Gv+lc2wt90kxXy/W0cn7IEWu3UPzewIjPGDH8ajDckvGzZx6pTGYJnTyMh7U6hUKwOBFPVLMWI7UwKQ==} + cpu: [arm64] + os: [linux] + + '@oxlint/linux-x64-gnu@0.11.1': + resolution: {integrity: sha512-D0tT8X0CsK/bpdkGdLSmsGftG3VndjyAUJuNGt56JYn0UfuPDkhQcLgUlkANHzNRXJ84tLQKhpf/MUDUHPB5cg==} + cpu: [x64] + os: [linux] + + '@oxlint/linux-x64-musl@0.11.1': + resolution: {integrity: sha512-WekaLYk8WLT7Di8+nyPvtqs9OlMoO6KjFDMlqqLDWQTk9ffjn8e76PCRigF3w39jQ70qP3c8k8cNKNw5ROuFcg==} + cpu: [x64] + os: [linux] + + '@oxlint/win32-arm64@0.11.1': + resolution: {integrity: sha512-/CN/bFtI33vB8uemOkZxlNRf6Q7CftP2pSO7a6Q2niG4NC99YRPj7ctXcPF0jGR0NQUhGZk7ajM4G/0MKcRdag==} + cpu: [arm64] + os: [win32] + + '@oxlint/win32-x64@0.11.1': + resolution: {integrity: sha512-0hLl0z6adYTvLIOPC5uyo+EAwNITkzi4AY4xImykQW8H89GhiV9Xl8MPJeZQMWSz7ajI1I2+hRsvA0QAzeBsxA==} + cpu: [x64] + os: [win32] + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} @@ -1786,6 +1823,11 @@ packages: engines: {node: '>= 20'} hasBin: true + oxlint@0.11.1: + resolution: {integrity: sha512-yVTkBmSvn1mo69vxBdNASOGFd1oqWzpaIWPFPIXNAHxgrW7FjotKuJ71j/pqtZH/sVSRWTpQFdmBa3CIuBEILg==} + engines: {node: '>=14.*'} + hasBin: true + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} @@ -2896,6 +2938,30 @@ snapshots: dependencies: '@octokit/openapi-types': 22.2.0 + '@oxlint/darwin-arm64@0.11.1': + optional: true + + '@oxlint/darwin-x64@0.11.1': + optional: true + + '@oxlint/linux-arm64-gnu@0.11.1': + optional: true + + '@oxlint/linux-arm64-musl@0.11.1': + optional: true + + '@oxlint/linux-x64-gnu@0.11.1': + optional: true + + '@oxlint/linux-x64-musl@0.11.1': + optional: true + + '@oxlint/win32-arm64@0.11.1': + optional: true + + '@oxlint/win32-x64@0.11.1': + optional: true + '@pkgjs/parseargs@0.11.0': optional: true @@ -3878,6 +3944,17 @@ snapshots: - debug - supports-color + oxlint@0.11.1: + optionalDependencies: + '@oxlint/darwin-arm64': 0.11.1 + '@oxlint/darwin-x64': 0.11.1 + '@oxlint/linux-arm64-gnu': 0.11.1 + '@oxlint/linux-arm64-musl': 0.11.1 + '@oxlint/linux-x64-gnu': 0.11.1 + '@oxlint/linux-x64-musl': 0.11.1 + '@oxlint/win32-arm64': 0.11.1 + '@oxlint/win32-x64': 0.11.1 + package-json-from-dist@1.0.1: {} parse-semver@1.1.1: From 41a0e60c3ec7a04fd31600f957ef70a3fbc49849 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Tue, 19 Nov 2024 01:05:30 +0000 Subject: [PATCH 035/121] refactor(ast)!: remove `impl GetAddress for Function` (#7343) `impl GetAddress for Function` was added as a hack, in the absence of another way to get the `Address` of a `&Function` (https://github.com/oxc-project/backlog/issues/140). Remove it, and use `Address:from_ptr` instead in JSX Refresh transform, which is only place using it. --- crates/oxc_ast/src/ast_impl/js.rs | 10 ---------- crates/oxc_transformer/src/jsx/refresh.rs | 7 ++++--- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 60d4f5ee9a5227..c0d6a549452a37 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -1011,16 +1011,6 @@ impl<'a> Function<'a> { } } -// FIXME: This is a workaround for we can't get current address by `TraverseCtx`, -// we will remove this once we support `TraverseCtx::current_address`. -// See: -impl GetAddress for Function<'_> { - #[inline] - fn address(&self) -> Address { - Address::from_ptr(self) - } -} - impl<'a> FormalParameters<'a> { /// Number of parameters bound in this parameter list. pub fn parameters_count(&self) -> usize { diff --git a/crates/oxc_transformer/src/jsx/refresh.rs b/crates/oxc_transformer/src/jsx/refresh.rs index f55dc2b4b90b05..78962ebaf40e79 100644 --- a/crates/oxc_transformer/src/jsx/refresh.rs +++ b/crates/oxc_transformer/src/jsx/refresh.rs @@ -2,7 +2,7 @@ use base64::prelude::{Engine, BASE64_STANDARD}; use rustc_hash::FxHashMap; use sha1::{Digest, Sha1}; -use oxc_allocator::{CloneIn, GetAddress, Vec as ArenaVec}; +use oxc_allocator::{Address, CloneIn, GetAddress, Vec as ArenaVec}; use oxc_ast::{ast::*, match_expression, AstBuilder, NONE}; use oxc_semantic::{Reference, ReferenceFlags, ScopeFlags, ScopeId, SymbolFlags}; use oxc_span::{Atom, GetSpan, SPAN}; @@ -289,8 +289,9 @@ impl<'a, 'ctx> Traverse<'a> for ReactRefresh<'a, 'ctx> { // which is a `Statement::ExportDefaultDeclaration` Ancestor::ExportDefaultDeclarationDeclaration(decl) => decl.address(), // Otherwise just a `function Foo() {}` - // which is a `Statement::FunctionDeclaration` - _ => func.address(), + // which is a `Statement::FunctionDeclaration`. + // `Function` is always stored in a `Box`, so has a stable memory address. + _ => Address::from_ptr(func), }; self.ctx.statement_injector.insert_after(&address, statement); } From 2534cdecb76f431190565426884d00e85c4e884b Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Tue, 19 Nov 2024 01:12:11 +0000 Subject: [PATCH 036/121] feat(syntax): add `AssignmentOperator::to_logical_operator` and `to_binary_operator` methods (#7350) Add methods to convert `AssignmentOperator` to `LogicalOperator` or `BinaryOperator`. e.g. `+=` -> `+`, `&&=` -> `&&`. --- crates/oxc_syntax/src/operator.rs | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/crates/oxc_syntax/src/operator.rs b/crates/oxc_syntax/src/operator.rs index 1a0a5e0eecda80..77519a34bd6778 100644 --- a/crates/oxc_syntax/src/operator.rs +++ b/crates/oxc_syntax/src/operator.rs @@ -95,6 +95,35 @@ impl AssignmentOperator { ) } + /// Get [`LogicalOperator`] corresponding to this [`AssignmentOperator`]. + pub fn to_logical_operator(self) -> Option { + match self { + Self::LogicalAnd => Some(LogicalOperator::And), + Self::LogicalOr => Some(LogicalOperator::Or), + Self::LogicalNullish => Some(LogicalOperator::Coalesce), + _ => None, + } + } + + /// Get [`BinaryOperator`] corresponding to this [`AssignmentOperator`]. + pub fn to_binary_operator(self) -> Option { + match self { + Self::Addition => Some(BinaryOperator::Addition), + Self::Subtraction => Some(BinaryOperator::Subtraction), + Self::Multiplication => Some(BinaryOperator::Multiplication), + Self::Division => Some(BinaryOperator::Division), + Self::Remainder => Some(BinaryOperator::Remainder), + Self::ShiftLeft => Some(BinaryOperator::ShiftLeft), + Self::ShiftRight => Some(BinaryOperator::ShiftRight), + Self::ShiftRightZeroFill => Some(BinaryOperator::ShiftRightZeroFill), + Self::BitwiseOR => Some(BinaryOperator::BitwiseOR), + Self::BitwiseXOR => Some(BinaryOperator::BitwiseXOR), + Self::BitwiseAnd => Some(BinaryOperator::BitwiseAnd), + Self::Exponential => Some(BinaryOperator::Exponential), + _ => None, + } + } + /// Get the string representation of this operator. /// /// This is the same as how the operator appears in source code. From 1d9f52866863a89fbb7d89dccac4a0d0241b10ac Mon Sep 17 00:00:00 2001 From: Ryan Walker Date: Mon, 18 Nov 2024 17:22:40 -0800 Subject: [PATCH 037/121] feat(linter): implement `unicorn/prefer-string-raw` lint rule (#7335) Implements [unicorn/refer-string-raw](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-string-raw.md) for #684 --- crates/oxc_linter/src/rules.rs | 2 + .../src/rules/unicorn/prefer_string_raw.rs | 283 ++++++++++++++++++ .../src/snapshots/prefer_string_raw.snap | 80 +++++ 3 files changed, 365 insertions(+) create mode 100644 crates/oxc_linter/src/rules/unicorn/prefer_string_raw.rs create mode 100644 crates/oxc_linter/src/snapshots/prefer_string_raw.snap diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index 381bce640d212d..da52c309ce71d4 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -358,6 +358,7 @@ mod unicorn { pub mod prefer_regexp_test; pub mod prefer_set_size; pub mod prefer_spread; + pub mod prefer_string_raw; pub mod prefer_string_replace_all; pub mod prefer_string_slice; pub mod prefer_string_starts_ends_with; @@ -946,6 +947,7 @@ oxc_macros::declare_all_lint_rules! { unicorn::prefer_regexp_test, unicorn::prefer_set_size, unicorn::prefer_spread, + unicorn::prefer_string_raw, unicorn::prefer_string_replace_all, unicorn::prefer_string_slice, unicorn::prefer_string_starts_ends_with, diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_string_raw.rs b/crates/oxc_linter/src/rules/unicorn/prefer_string_raw.rs new file mode 100644 index 00000000000000..8e67479592db29 --- /dev/null +++ b/crates/oxc_linter/src/rules/unicorn/prefer_string_raw.rs @@ -0,0 +1,283 @@ +use oxc_ast::{ + ast::{JSXAttributeValue, PropertyKey, TSEnumMemberName}, + AstKind, +}; +use oxc_diagnostics::OxcDiagnostic; +use oxc_ecmascript::StringCharAt; +use oxc_macros::declare_oxc_lint; +use oxc_span::Span; +use oxc_syntax::keyword::RESERVED_KEYWORDS; + +use crate::{context::LintContext, rule::Rule, AstNode}; + +fn prefer_string_raw(span: Span) -> OxcDiagnostic { + OxcDiagnostic::warn(r"`String.raw` should be used to avoid escaping `\`.").with_label(span) +} + +#[derive(Debug, Default, Clone)] +pub struct PreferStringRaw; + +declare_oxc_lint!( + /// ### What it does + /// + /// Prefers use of String.raw to avoid escaping \. + /// + /// ### Why is this bad? + /// + /// Excessive backslashes can make string values less readable which can be avoided by using `String.raw`. + /// + /// ### Example + /// + /// Examples of **incorrect** code for this rule: + /// ```javascript + /// const file = "C:\\windows\\style\\path\\to\\file.js"; + /// const regexp = new RegExp('foo\\.bar'); + /// ``` + /// + /// Examples of **correct** code for this rule: + /// ```javascript + /// const file = String.raw`C:\windows\style\path\to\file.js`; + /// const regexp = new RegExp(String.raw`foo\.bar`); + /// ``` + PreferStringRaw, + style, + fix, +); + +fn unescape_backslash(input: &str, quote: char) -> String { + let mut result = String::with_capacity(input.len()); + let mut chars = input.chars().peekable(); + + while let Some(c) = chars.next() { + if c == '\\' { + if let Some(next) = chars.peek() { + if *next == '\\' || *next == quote { + result.push(*next); + chars.next(); + continue; + } + } + } + + result.push(c); + } + + result +} + +impl Rule for PreferStringRaw { + #[allow(clippy::cast_precision_loss)] + fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { + let AstKind::StringLiteral(string_literal) = node.kind() else { + return; + }; + + let parent_node = ctx.nodes().parent_node(node.id()); + + if let Some(parent_node) = parent_node { + match parent_node.kind() { + AstKind::Directive(_) => { + return; + } + AstKind::ImportDeclaration(decl) => { + if string_literal.span == decl.source.span { + return; + } + } + AstKind::ExportNamedDeclaration(decl) => { + if let Some(source) = &decl.source { + if string_literal.span == source.span { + return; + } + } + } + AstKind::ExportAllDeclaration(decl) => { + if string_literal.span == decl.source.span { + return; + } + } + AstKind::ObjectProperty(prop) => { + let PropertyKey::StringLiteral(key) = &prop.key else { + return; + }; + + if !prop.computed && string_literal.span == key.span { + return; + } + } + AstKind::PropertyKey(_) => { + if let Some(AstKind::ObjectProperty(prop)) = + ctx.nodes().parent_node(parent_node.id()).map(AstNode::kind) + { + let PropertyKey::StringLiteral(key) = &prop.key else { + return; + }; + + if !prop.computed && key.span == string_literal.span { + return; + } + } + } + AstKind::JSXAttributeItem(attr) => { + let Some(attr) = attr.as_attribute() else { + return; + }; + + let Some(JSXAttributeValue::StringLiteral(value)) = &attr.value else { + return; + }; + + if value.span == string_literal.span { + return; + } + } + AstKind::TSEnumMember(member) => { + if member.span == string_literal.span { + return; + }; + + let TSEnumMemberName::String(id) = &member.id else { + return; + }; + + if id.span == string_literal.span { + return; + } + } + _ => {} + } + } + + let raw = ctx.source_range(string_literal.span); + + let last_char_index = raw.len() - 2; + if raw.char_at(Some(last_char_index as f64)) == Some('\\') { + return; + } + + if !raw.contains(r"\\") || raw.contains('`') || raw.contains("${") { + return; + } + + let Some(quote) = raw.char_at(Some(0.0)) else { + return; + }; + + let trimmed = ctx.source_range(string_literal.span.shrink(1)); + + let unescaped = unescape_backslash(trimmed, quote); + + if unescaped != string_literal.value.as_ref() { + return; + } + + ctx.diagnostic_with_fix(prefer_string_raw(string_literal.span), |fixer| { + let end = string_literal.span.start; + let before = ctx.source_range(oxc_span::Span::new(0, end)); + + let mut fix = format!("String.raw`{unescaped}`"); + + if ends_with_keyword(before) { + fix = format!(" {fix}"); + } + + fixer.replace(string_literal.span, fix) + }); + } +} + +fn ends_with_keyword(source: &str) -> bool { + for keyword in &RESERVED_KEYWORDS { + if source.ends_with(keyword) { + return true; + } + } + + if source.ends_with("of") { + return true; + } + + false +} + +#[test] +fn test() { + use crate::tester::Tester; + + let pass: Vec<&str> = vec![ + r"const file = String.raw`C:\windows\style\path\to\file.js`;", + r"const regexp = new RegExp(String.raw`foo\.bar`);", + r"a = '\''", + r"'a\\b'", + r#"import foo from "./foo\\bar.js";"#, + r#"export {foo} from "./foo\\bar.js";"#, + r#"export * from "./foo\\bar.js";"#, + r"a = {'a\\b': 1}", + " + a = '\\\\a \\ + b' + ", + r"a = 'a\\b\u{51}c'", + "a = 'a\\\\b`'", + "a = 'a\\\\b${foo}'", + r#""#, + r#" + enum Files { + Foo = "C:\\\\path\\\\to\\\\foo.js", + } + "#, + r#" + enum Foo { + "\\\\a\\\\b" = "baz", + } + "#, + r"const a = 'a\\';", + ]; + + let fail = vec![ + r#"const file = "C:\\windows\\style\\path\\to\\file.js";"#, + r"const regexp = new RegExp('foo\\.bar');", + r"a = 'a\\b'", + r"a = {['a\\b']: b}", + r"function a() {return'a\\b'}", + r"function* a() {yield'a\\b'}", + r"function a() {throw'a\\b'}", + r"if (typeof'a\\b' === 'string') {}", + r"const a = () => void'a\\b';", + r"const foo = 'foo \\x46';", + r"for (const f of'a\\b') {}", + ]; + + let fix = vec![ + ( + r#"const file = "C:\\windows\\style\\path\\to\\file.js";"#, + r"const file = String.raw`C:\windows\style\path\to\file.js`;", + None, + ), + ( + r"const regexp = new RegExp('foo\\.bar');", + r"const regexp = new RegExp(String.raw`foo\.bar`);", + None, + ), + (r"a = 'a\\b'", r"a = String.raw`a\b`", None), + (r"a = {['a\\b']: b}", r"a = {[String.raw`a\b`]: b}", None), + (r"function a() {return'a\\b'}", r"function a() {return String.raw`a\b`}", None), + (r"const foo = 'foo \\x46';", r"const foo = String.raw`foo \x46`;", None), + (r"for (const f of'a\\b') {}", r"for (const f of String.raw`a\b`) {}", None), + (r"a = 'a\\b'", r"a = String.raw`a\b`", None), + (r"a = {['a\\b']: b}", r"a = {[String.raw`a\b`]: b}", None), + (r"function a() {return'a\\b'}", r"function a() {return String.raw`a\b`}", None), + (r"function* a() {yield'a\\b'}", r"function* a() {yield String.raw`a\b`}", None), + (r"function a() {throw'a\\b'}", r"function a() {throw String.raw`a\b`}", None), + ( + r"if (typeof'a\\b' === 'string') {}", + r"if (typeof String.raw`a\b` === 'string') {}", + None, + ), + (r"const a = () => void'a\\b';", r"const a = () => void String.raw`a\b`;", None), + (r"const foo = 'foo \\x46';", r"const foo = String.raw`foo \x46`;", None), + (r"for (const f of'a\\b') {}", r"for (const f of String.raw`a\b`) {}", None), + ]; + + Tester::new(PreferStringRaw::NAME, pass, fail).expect_fix(fix).test_and_snapshot(); +} diff --git a/crates/oxc_linter/src/snapshots/prefer_string_raw.snap b/crates/oxc_linter/src/snapshots/prefer_string_raw.snap new file mode 100644 index 00000000000000..6e096da94a656f --- /dev/null +++ b/crates/oxc_linter/src/snapshots/prefer_string_raw.snap @@ -0,0 +1,80 @@ +--- +source: crates/oxc_linter/src/tester.rs +snapshot_kind: text +--- + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:14] + 1 β”‚ const file = "C:\\windows\\style\\path\\to\\file.js"; + Β· ─────────────────────────────────────── + ╰──── + help: Replace `"C:\\windows\\style\\path\\to\\file.js"` with `String.raw`C:\windows\style\path\to\file.js``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:27] + 1 β”‚ const regexp = new RegExp('foo\\.bar'); + Β· ─────────── + ╰──── + help: Replace `'foo\\.bar'` with `String.raw`foo\.bar``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:5] + 1 β”‚ a = 'a\\b' + Β· ────── + ╰──── + help: Replace `'a\\b'` with `String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:7] + 1 β”‚ a = {['a\\b']: b} + Β· ────── + ╰──── + help: Replace `'a\\b'` with `String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:21] + 1 β”‚ function a() {return'a\\b'} + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:21] + 1 β”‚ function* a() {yield'a\\b'} + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:20] + 1 β”‚ function a() {throw'a\\b'} + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:11] + 1 β”‚ if (typeof'a\\b' === 'string') {} + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:21] + 1 β”‚ const a = () => void'a\\b'; + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:13] + 1 β”‚ const foo = 'foo \\x46'; + Β· ─────────── + ╰──── + help: Replace `'foo \\x46'` with `String.raw`foo \x46``. + + ⚠ eslint-plugin-unicorn(prefer-string-raw): `String.raw` should be used to avoid escaping `\`. + ╭─[prefer_string_raw.tsx:1:16] + 1 β”‚ for (const f of'a\\b') {} + Β· ────── + ╰──── + help: Replace `'a\\b'` with ` String.raw`a\b``. From bc0e72c1e286d9015c8ab60ef0200761ab41e7e7 Mon Sep 17 00:00:00 2001 From: Dmitry Zakharov Date: Tue, 19 Nov 2024 04:23:16 +0300 Subject: [PATCH 038/121] fix(linter): handle user variables correctly for import/no_commonjs (#7316) test case found in `typescript/no-require-imports` --- crates/oxc_linter/src/rules/import/no_commonjs.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/crates/oxc_linter/src/rules/import/no_commonjs.rs b/crates/oxc_linter/src/rules/import/no_commonjs.rs index 0dc3151028d402..8dc2f16c5fac1b 100644 --- a/crates/oxc_linter/src/rules/import/no_commonjs.rs +++ b/crates/oxc_linter/src/rules/import/no_commonjs.rs @@ -10,7 +10,6 @@ use oxc_ast::{ use crate::{context::LintContext, rule::Rule, AstNode}; fn no_commonjs_diagnostic(span: Span, name: &str, actual: &str) -> OxcDiagnostic { - // See for details OxcDiagnostic::warn(format!("Expected {name} instead of {actual}")) .with_help("Do not use CommonJS `require` calls and `module.exports` or `exports.*`") .with_label(span) @@ -214,6 +213,10 @@ impl Rule for NoCommonjs { return; } + if ctx.scopes().find_binding(ctx.scopes().root_scope_id(), "require").is_some() { + return; + } + if let Argument::TemplateLiteral(template_literal) = &call_expr.arguments[0] { if template_literal.expressions.len() != 0 { return; @@ -299,6 +302,15 @@ fn test() { Some(json!([{ "allowRequire": false }])), ), (r#"try { require("x") } catch (error) {}"#, None), + // covers user variables + ( + " + import { createRequire } from 'module'; + const require = createRequire(); + require('remark-preset-prettier'); + ", + None, + ), ]; let fail = vec![ From c335f92ada8e810c051d19b686f78bf0e6b312f6 Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Tue, 19 Nov 2024 01:23:28 +0000 Subject: [PATCH 039/121] perf(syntax): reorder operator enum variants (#7351) Re-order enum variants of `AssignmentOperator`, `BinaryOperator` and `UnaryOperator`. * `Exponential` moved to after `Remainder` (so with the rest of the arithmetic operators). * `Shift*` operators follow arithmetic operators. * `AssignmentOperator::Bitwise*` ops moved to before `Logical*` ops (so all ops which correspond to `BinaryOperator`s are together). * `*Or` always before `*And`. * Plus/Addition always before Minus/Subtraction. The purpose is to make the various methods on these types maximally efficient: 1. Group together variants so that `AssignmentOperator::is_*` methods can be executed with the minimum number of operations (essentially `variant - min <= max`). 2. Align the variants of `AssignmentOperator` and `BinaryOperator` so that conversion methods added in #7350 become very cheap too (essentially `if variant - min <= max { Some(variant + offset) } else { None }`). --- .../src/generated/derive_clone_in.rs | 14 +-- .../oxc_syntax/src/generated/derive_estree.rs | 78 ++++++------ crates/oxc_syntax/src/operator.rs | 112 +++++++++--------- npm/oxc-types/types.d.ts | 18 +-- 4 files changed, 111 insertions(+), 111 deletions(-) diff --git a/crates/oxc_syntax/src/generated/derive_clone_in.rs b/crates/oxc_syntax/src/generated/derive_clone_in.rs index 9af592332c53fa..d0a01e2b57a0ee 100644 --- a/crates/oxc_syntax/src/generated/derive_clone_in.rs +++ b/crates/oxc_syntax/src/generated/derive_clone_in.rs @@ -44,16 +44,16 @@ impl<'alloc> CloneIn<'alloc> for AssignmentOperator { Self::Multiplication => AssignmentOperator::Multiplication, Self::Division => AssignmentOperator::Division, Self::Remainder => AssignmentOperator::Remainder, + Self::Exponential => AssignmentOperator::Exponential, Self::ShiftLeft => AssignmentOperator::ShiftLeft, Self::ShiftRight => AssignmentOperator::ShiftRight, Self::ShiftRightZeroFill => AssignmentOperator::ShiftRightZeroFill, Self::BitwiseOR => AssignmentOperator::BitwiseOR, Self::BitwiseXOR => AssignmentOperator::BitwiseXOR, Self::BitwiseAnd => AssignmentOperator::BitwiseAnd, - Self::LogicalAnd => AssignmentOperator::LogicalAnd, Self::LogicalOr => AssignmentOperator::LogicalOr, + Self::LogicalAnd => AssignmentOperator::LogicalAnd, Self::LogicalNullish => AssignmentOperator::LogicalNullish, - Self::Exponential => AssignmentOperator::Exponential, } } } @@ -70,20 +70,20 @@ impl<'alloc> CloneIn<'alloc> for BinaryOperator { Self::LessEqualThan => BinaryOperator::LessEqualThan, Self::GreaterThan => BinaryOperator::GreaterThan, Self::GreaterEqualThan => BinaryOperator::GreaterEqualThan, - Self::ShiftLeft => BinaryOperator::ShiftLeft, - Self::ShiftRight => BinaryOperator::ShiftRight, - Self::ShiftRightZeroFill => BinaryOperator::ShiftRightZeroFill, Self::Addition => BinaryOperator::Addition, Self::Subtraction => BinaryOperator::Subtraction, Self::Multiplication => BinaryOperator::Multiplication, Self::Division => BinaryOperator::Division, Self::Remainder => BinaryOperator::Remainder, + Self::Exponential => BinaryOperator::Exponential, + Self::ShiftLeft => BinaryOperator::ShiftLeft, + Self::ShiftRight => BinaryOperator::ShiftRight, + Self::ShiftRightZeroFill => BinaryOperator::ShiftRightZeroFill, Self::BitwiseOR => BinaryOperator::BitwiseOR, Self::BitwiseXOR => BinaryOperator::BitwiseXOR, Self::BitwiseAnd => BinaryOperator::BitwiseAnd, Self::In => BinaryOperator::In, Self::Instanceof => BinaryOperator::Instanceof, - Self::Exponential => BinaryOperator::Exponential, } } } @@ -103,8 +103,8 @@ impl<'alloc> CloneIn<'alloc> for UnaryOperator { type Cloned = UnaryOperator; fn clone_in(&self, _: &'alloc Allocator) -> Self::Cloned { match self { - Self::UnaryNegation => UnaryOperator::UnaryNegation, Self::UnaryPlus => UnaryOperator::UnaryPlus, + Self::UnaryNegation => UnaryOperator::UnaryNegation, Self::LogicalNot => UnaryOperator::LogicalNot, Self::BitwiseNot => UnaryOperator::BitwiseNot, Self::Typeof => UnaryOperator::Typeof, diff --git a/crates/oxc_syntax/src/generated/derive_estree.rs b/crates/oxc_syntax/src/generated/derive_estree.rs index 6f13c8607fd165..896ded18bbe63b 100644 --- a/crates/oxc_syntax/src/generated/derive_estree.rs +++ b/crates/oxc_syntax/src/generated/derive_estree.rs @@ -28,35 +28,35 @@ impl Serialize for AssignmentOperator { AssignmentOperator::Remainder => { serializer.serialize_unit_variant("AssignmentOperator", 5u32, "%=") } + AssignmentOperator::Exponential => { + serializer.serialize_unit_variant("AssignmentOperator", 6u32, "**=") + } AssignmentOperator::ShiftLeft => { - serializer.serialize_unit_variant("AssignmentOperator", 6u32, "<<=") + serializer.serialize_unit_variant("AssignmentOperator", 7u32, "<<=") } AssignmentOperator::ShiftRight => { - serializer.serialize_unit_variant("AssignmentOperator", 7u32, ">>=") + serializer.serialize_unit_variant("AssignmentOperator", 8u32, ">>=") } AssignmentOperator::ShiftRightZeroFill => { - serializer.serialize_unit_variant("AssignmentOperator", 8u32, ">>>=") + serializer.serialize_unit_variant("AssignmentOperator", 9u32, ">>>=") } AssignmentOperator::BitwiseOR => { - serializer.serialize_unit_variant("AssignmentOperator", 9u32, "|=") + serializer.serialize_unit_variant("AssignmentOperator", 10u32, "|=") } AssignmentOperator::BitwiseXOR => { - serializer.serialize_unit_variant("AssignmentOperator", 10u32, "^=") + serializer.serialize_unit_variant("AssignmentOperator", 11u32, "^=") } AssignmentOperator::BitwiseAnd => { - serializer.serialize_unit_variant("AssignmentOperator", 11u32, "&=") - } - AssignmentOperator::LogicalAnd => { - serializer.serialize_unit_variant("AssignmentOperator", 12u32, "&&=") + serializer.serialize_unit_variant("AssignmentOperator", 12u32, "&=") } AssignmentOperator::LogicalOr => { serializer.serialize_unit_variant("AssignmentOperator", 13u32, "||=") } - AssignmentOperator::LogicalNullish => { - serializer.serialize_unit_variant("AssignmentOperator", 14u32, "??=") + AssignmentOperator::LogicalAnd => { + serializer.serialize_unit_variant("AssignmentOperator", 14u32, "&&=") } - AssignmentOperator::Exponential => { - serializer.serialize_unit_variant("AssignmentOperator", 15u32, "**=") + AssignmentOperator::LogicalNullish => { + serializer.serialize_unit_variant("AssignmentOperator", 15u32, "??=") } } } @@ -89,45 +89,45 @@ impl Serialize for BinaryOperator { BinaryOperator::GreaterEqualThan => { serializer.serialize_unit_variant("BinaryOperator", 7u32, ">=") } - BinaryOperator::ShiftLeft => { - serializer.serialize_unit_variant("BinaryOperator", 8u32, "<<") - } - BinaryOperator::ShiftRight => { - serializer.serialize_unit_variant("BinaryOperator", 9u32, ">>") - } - BinaryOperator::ShiftRightZeroFill => { - serializer.serialize_unit_variant("BinaryOperator", 10u32, ">>>") - } BinaryOperator::Addition => { - serializer.serialize_unit_variant("BinaryOperator", 11u32, "+") + serializer.serialize_unit_variant("BinaryOperator", 8u32, "+") } BinaryOperator::Subtraction => { - serializer.serialize_unit_variant("BinaryOperator", 12u32, "-") + serializer.serialize_unit_variant("BinaryOperator", 9u32, "-") } BinaryOperator::Multiplication => { - serializer.serialize_unit_variant("BinaryOperator", 13u32, "*") + serializer.serialize_unit_variant("BinaryOperator", 10u32, "*") } BinaryOperator::Division => { - serializer.serialize_unit_variant("BinaryOperator", 14u32, "/") + serializer.serialize_unit_variant("BinaryOperator", 11u32, "/") } BinaryOperator::Remainder => { - serializer.serialize_unit_variant("BinaryOperator", 15u32, "%") + serializer.serialize_unit_variant("BinaryOperator", 12u32, "%") + } + BinaryOperator::Exponential => { + serializer.serialize_unit_variant("BinaryOperator", 13u32, "**") + } + BinaryOperator::ShiftLeft => { + serializer.serialize_unit_variant("BinaryOperator", 14u32, "<<") + } + BinaryOperator::ShiftRight => { + serializer.serialize_unit_variant("BinaryOperator", 15u32, ">>") + } + BinaryOperator::ShiftRightZeroFill => { + serializer.serialize_unit_variant("BinaryOperator", 16u32, ">>>") } BinaryOperator::BitwiseOR => { - serializer.serialize_unit_variant("BinaryOperator", 16u32, "|") + serializer.serialize_unit_variant("BinaryOperator", 17u32, "|") } BinaryOperator::BitwiseXOR => { - serializer.serialize_unit_variant("BinaryOperator", 17u32, "^") + serializer.serialize_unit_variant("BinaryOperator", 18u32, "^") } BinaryOperator::BitwiseAnd => { - serializer.serialize_unit_variant("BinaryOperator", 18u32, "&") + serializer.serialize_unit_variant("BinaryOperator", 19u32, "&") } - BinaryOperator::In => serializer.serialize_unit_variant("BinaryOperator", 19u32, "in"), + BinaryOperator::In => serializer.serialize_unit_variant("BinaryOperator", 20u32, "in"), BinaryOperator::Instanceof => { - serializer.serialize_unit_variant("BinaryOperator", 20u32, "instanceof") - } - BinaryOperator::Exponential => { - serializer.serialize_unit_variant("BinaryOperator", 21u32, "**") + serializer.serialize_unit_variant("BinaryOperator", 21u32, "instanceof") } } } @@ -150,11 +150,11 @@ impl Serialize for LogicalOperator { impl Serialize for UnaryOperator { fn serialize(&self, serializer: S) -> Result { match *self { - UnaryOperator::UnaryNegation => { - serializer.serialize_unit_variant("UnaryOperator", 0u32, "-") - } UnaryOperator::UnaryPlus => { - serializer.serialize_unit_variant("UnaryOperator", 1u32, "+") + serializer.serialize_unit_variant("UnaryOperator", 0u32, "+") + } + UnaryOperator::UnaryNegation => { + serializer.serialize_unit_variant("UnaryOperator", 1u32, "-") } UnaryOperator::LogicalNot => { serializer.serialize_unit_variant("UnaryOperator", 2u32, "!") diff --git a/crates/oxc_syntax/src/operator.rs b/crates/oxc_syntax/src/operator.rs index 77519a34bd6778..0d965e7e6b932b 100644 --- a/crates/oxc_syntax/src/operator.rs +++ b/crates/oxc_syntax/src/operator.rs @@ -37,42 +37,42 @@ pub enum AssignmentOperator { /// `%=` #[estree(rename = "%=")] Remainder = 5, + /// `**=` + #[estree(rename = "**=")] + Exponential = 6, /// `<<=` #[estree(rename = "<<=")] - ShiftLeft = 6, + ShiftLeft = 7, /// `>>=` #[estree(rename = ">>=")] - ShiftRight = 7, + ShiftRight = 8, /// `>>>=` #[estree(rename = ">>>=")] - ShiftRightZeroFill = 8, + ShiftRightZeroFill = 9, /// `|=` #[estree(rename = "|=")] - BitwiseOR = 9, + BitwiseOR = 10, /// `^=` #[estree(rename = "^=")] - BitwiseXOR = 10, + BitwiseXOR = 11, /// `&=` #[estree(rename = "&=")] - BitwiseAnd = 11, - /// `&&=` - #[estree(rename = "&&=")] - LogicalAnd = 12, + BitwiseAnd = 12, /// `||=` #[estree(rename = "||=")] LogicalOr = 13, + /// `&&=` + #[estree(rename = "&&=")] + LogicalAnd = 14, /// `??=` #[estree(rename = "??=")] - LogicalNullish = 14, - /// `**=` - #[estree(rename = "**=")] - Exponential = 15, + LogicalNullish = 15, } impl AssignmentOperator { /// Returns `true` for '||=`, `&&=`, and `??=`. pub fn is_logical(self) -> bool { - matches!(self, Self::LogicalAnd | Self::LogicalOr | Self::LogicalNullish) + matches!(self, Self::LogicalOr | Self::LogicalAnd | Self::LogicalNullish) } /// Returns `true` for `+=`, `-=`, `*=`, `/=`, `%=`, and `**=`. @@ -90,16 +90,16 @@ impl AssignmentOperator { pub fn is_bitwise(self) -> bool { matches!( self, - Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd - | Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill + Self::ShiftLeft | Self::ShiftRight | Self::ShiftRightZeroFill + | Self::BitwiseOR | Self::BitwiseXOR | Self::BitwiseAnd ) } /// Get [`LogicalOperator`] corresponding to this [`AssignmentOperator`]. pub fn to_logical_operator(self) -> Option { match self { - Self::LogicalAnd => Some(LogicalOperator::And), Self::LogicalOr => Some(LogicalOperator::Or), + Self::LogicalAnd => Some(LogicalOperator::And), Self::LogicalNullish => Some(LogicalOperator::Coalesce), _ => None, } @@ -113,13 +113,13 @@ impl AssignmentOperator { Self::Multiplication => Some(BinaryOperator::Multiplication), Self::Division => Some(BinaryOperator::Division), Self::Remainder => Some(BinaryOperator::Remainder), + Self::Exponential => Some(BinaryOperator::Exponential), Self::ShiftLeft => Some(BinaryOperator::ShiftLeft), Self::ShiftRight => Some(BinaryOperator::ShiftRight), Self::ShiftRightZeroFill => Some(BinaryOperator::ShiftRightZeroFill), Self::BitwiseOR => Some(BinaryOperator::BitwiseOR), Self::BitwiseXOR => Some(BinaryOperator::BitwiseXOR), Self::BitwiseAnd => Some(BinaryOperator::BitwiseAnd), - Self::Exponential => Some(BinaryOperator::Exponential), _ => None, } } @@ -135,16 +135,16 @@ impl AssignmentOperator { Self::Multiplication => "*=", Self::Division => "/=", Self::Remainder => "%=", + Self::Exponential => "**=", Self::ShiftLeft => "<<=", Self::ShiftRight => ">>=", Self::ShiftRightZeroFill => ">>>=", Self::BitwiseOR => "|=", Self::BitwiseXOR => "^=", Self::BitwiseAnd => "&=", - Self::LogicalAnd => "&&=", Self::LogicalOr => "||=", + Self::LogicalAnd => "&&=", Self::LogicalNullish => "??=", - Self::Exponential => "**=", } } } @@ -182,48 +182,48 @@ pub enum BinaryOperator { /// `>=` #[estree(rename = ">=")] GreaterEqualThan = 7, - /// `<<` - #[estree(rename = "<<")] - ShiftLeft = 8, - /// `>>` - #[estree(rename = ">>")] - ShiftRight = 9, - /// `>>>` - #[estree(rename = ">>>")] - ShiftRightZeroFill = 10, /// `+` #[estree(rename = "+")] - Addition = 11, + Addition = 8, /// `-` #[estree(rename = "-")] - Subtraction = 12, + Subtraction = 9, /// `*` #[estree(rename = "*")] - Multiplication = 13, + Multiplication = 10, /// `/` #[estree(rename = "/")] - Division = 14, + Division = 11, /// `%` #[estree(rename = "%")] - Remainder = 15, + Remainder = 12, + /// `**` + #[estree(rename = "**")] + Exponential = 13, + /// `<<` + #[estree(rename = "<<")] + ShiftLeft = 14, + /// `>>` + #[estree(rename = ">>")] + ShiftRight = 15, + /// `>>>` + #[estree(rename = ">>>")] + ShiftRightZeroFill = 16, /// `|` #[estree(rename = "|")] - BitwiseOR = 16, + BitwiseOR = 17, /// `^` #[estree(rename = "^")] - BitwiseXOR = 17, + BitwiseXOR = 18, /// `&` #[estree(rename = "&")] - BitwiseAnd = 18, + BitwiseAnd = 19, /// `in` #[estree(rename = "in")] - In = 19, + In = 20, /// `instanceof` #[estree(rename = "instanceof")] - Instanceof = 20, - /// `**` - #[estree(rename = "**")] - Exponential = 21, + Instanceof = 21, } impl BinaryOperator { @@ -262,7 +262,7 @@ impl BinaryOperator { /// Returns `true` if this is an [`In`](BinaryOperator::In) operator. pub fn is_in(self) -> bool { - matches!(self, Self::In) + self == Self::In } /// Returns `true` for any bitwise operator @@ -321,20 +321,20 @@ impl BinaryOperator { Self::LessEqualThan => "<=", Self::GreaterThan => ">", Self::GreaterEqualThan => ">=", - Self::ShiftLeft => "<<", - Self::ShiftRight => ">>", - Self::ShiftRightZeroFill => ">>>", Self::Addition => "+", Self::Subtraction => "-", Self::Multiplication => "*", Self::Division => "/", Self::Remainder => "%", + Self::Exponential => "**", + Self::ShiftLeft => "<<", + Self::ShiftRight => ">>", + Self::ShiftRightZeroFill => ">>>", Self::BitwiseOR => "|", Self::BitwiseXOR => "^", Self::BitwiseAnd => "&", Self::In => "in", Self::Instanceof => "instanceof", - Self::Exponential => "**", } } @@ -444,12 +444,12 @@ impl GetPrecedence for LogicalOperator { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[generate_derive(CloneIn, ContentEq, ContentHash, ESTree)] pub enum UnaryOperator { - /// `-` - #[estree(rename = "-")] - UnaryNegation = 0, /// `+` #[estree(rename = "+")] - UnaryPlus = 1, + UnaryPlus = 0, + /// `-` + #[estree(rename = "-")] + UnaryNegation = 1, /// `!` #[estree(rename = "!")] LogicalNot = 2, @@ -470,24 +470,24 @@ pub enum UnaryOperator { impl UnaryOperator { /// Returns `true` if this operator is a unary arithmetic operator. pub fn is_arithmetic(self) -> bool { - matches!(self, Self::UnaryNegation | Self::UnaryPlus) + matches!(self, Self::UnaryPlus | Self::UnaryNegation) } /// Returns `true` if this operator is a [`LogicalNot`]. /// /// [`LogicalNot`]: UnaryOperator::LogicalNot pub fn is_not(self) -> bool { - matches!(self, Self::LogicalNot) + self == Self::LogicalNot } /// Returns `true` if this operator is a bitwise operator. pub fn is_bitwise(self) -> bool { - matches!(self, Self::BitwiseNot) + self == Self::BitwiseNot } /// Returns `true` if this is the [`void`](UnaryOperator::Void) operator. pub fn is_void(self) -> bool { - matches!(self, Self::Void) + self == Self::Void } /// Returns `true` if this operator is a keyword instead of punctuation. @@ -498,8 +498,8 @@ impl UnaryOperator { /// Get the string representation of this operator as it appears in source code. pub fn as_str(&self) -> &'static str { match self { - Self::UnaryNegation => "-", Self::UnaryPlus => "+", + Self::UnaryNegation => "-", Self::LogicalNot => "!", Self::BitwiseNot => "~", Self::Typeof => "typeof", diff --git a/npm/oxc-types/types.d.ts b/npm/oxc-types/types.d.ts index cab36984c1aa0d..2bdf1d602067fd 100644 --- a/npm/oxc-types/types.d.ts +++ b/npm/oxc-types/types.d.ts @@ -1714,16 +1714,16 @@ export type AssignmentOperator = | '*=' | '/=' | '%=' + | '**=' | '<<=' | '>>=' | '>>>=' | '|=' | '^=' | '&=' - | '&&=' | '||=' - | '??=' - | '**='; + | '&&=' + | '??='; export type BinaryOperator = | '==' @@ -1734,24 +1734,24 @@ export type BinaryOperator = | '<=' | '>' | '>=' - | '<<' - | '>>' - | '>>>' | '+' | '-' | '*' | '/' | '%' + | '**' + | '<<' + | '>>' + | '>>>' | '|' | '^' | '&' | 'in' - | 'instanceof' - | '**'; + | 'instanceof'; export type LogicalOperator = '||' | '&&' | '??'; -export type UnaryOperator = '-' | '+' | '!' | '~' | 'typeof' | 'void' | 'delete'; +export type UnaryOperator = '+' | '-' | '!' | '~' | 'typeof' | 'void' | 'delete'; export type UpdateOperator = '++' | '--'; From 4c367b67462f25933e25825351438d8c3a3be312 Mon Sep 17 00:00:00 2001 From: Boshen Date: Tue, 19 Nov 2024 16:01:09 +0800 Subject: [PATCH 040/121] chore(deps): update codecov/codecov-action action to v5 (#7353) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/codecov.yml b/.github/workflows/codecov.yml index db92ce669dc1ec..989ff44c76271e 100644 --- a/.github/workflows/codecov.yml +++ b/.github/workflows/codecov.yml @@ -66,7 +66,7 @@ jobs: - name: Upload to codecov.io if: env.CODECOV_TOKEN - uses: codecov/codecov-action@v4 + uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} fail_ci_if_error: true From 65f1e82bd89336c6cb5cfe348bcbda0da7945a6f Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 09:15:14 +0000 Subject: [PATCH 041/121] refactor(transform_conformance): clean up some code (#7354) --- tasks/transform_conformance/src/constants.rs | 6 +- tasks/transform_conformance/src/exec.rs | 30 ++++++++++ tasks/transform_conformance/src/lib.rs | 61 +++++--------------- 3 files changed, 48 insertions(+), 49 deletions(-) create mode 100644 tasks/transform_conformance/src/exec.rs diff --git a/tasks/transform_conformance/src/constants.rs b/tasks/transform_conformance/src/constants.rs index dc0b3e7288cd92..3eaf32940804f5 100644 --- a/tasks/transform_conformance/src/constants.rs +++ b/tasks/transform_conformance/src/constants.rs @@ -1,4 +1,4 @@ -pub(crate) const PLUGINS: &[&str] = &[ +pub const PLUGINS: &[&str] = &[ "babel-preset-env", // // ES2024 // "babel-plugin-transform-unicode-sets-regex", @@ -61,7 +61,7 @@ pub(crate) const PLUGINS: &[&str] = &[ "regexp", ]; -pub(crate) const PLUGINS_NOT_SUPPORTED_YET: &[&str] = &[ +pub const PLUGINS_NOT_SUPPORTED_YET: &[&str] = &[ "proposal-decorators", "transform-class-properties", "transform-classes", @@ -74,7 +74,7 @@ pub(crate) const PLUGINS_NOT_SUPPORTED_YET: &[&str] = &[ "transform-react-constant-elements", ]; -pub(crate) const SKIP_TESTS: &[&str] = &[ +pub const SKIP_TESTS: &[&str] = &[ // Shouldn't report in transformer "babel-plugin-transform-typescript/test/fixtures/node-extensions/type-assertion-in-cts", "babel-plugin-transform-typescript/test/fixtures/node-extensions/type-assertion-in-mts", diff --git a/tasks/transform_conformance/src/exec.rs b/tasks/transform_conformance/src/exec.rs new file mode 100644 index 00000000000000..40cf07d1fe12d9 --- /dev/null +++ b/tasks/transform_conformance/src/exec.rs @@ -0,0 +1,30 @@ +use std::{path::Path, process::Command}; + +use crate::{conformance_root, TestRunner}; + +impl TestRunner { + pub(crate) fn run_vitest(&self, dest: &Path) { + let version = String::from("node: ") + + &String::from_utf8(Command::new("node").arg("--version").output().unwrap().stdout) + .unwrap(); + let output = Command::new("node") + .current_dir(conformance_root()) + .env("NO_COLOR", "1") + .args([ + "--run", + "vitest", + "--", + "run", + "--reporter=basic", + "--exclude=\"\"", + "--no-color", + "./fixtures", + ]) + .output() + .unwrap(); + let content = if output.stderr.is_empty() { output.stdout } else { output.stderr }; + let output = String::from_utf8(content).unwrap(); + let output = version + &output; + self.snapshot.save(dest, &output); + } +} diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index d97a0a261adefc..3620ec70f2af6e 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -1,10 +1,13 @@ #![allow(clippy::print_stdout, clippy::print_stderr)] mod constants; +mod driver; +mod exec; +mod test_case; + use std::{ fs, path::{Path, PathBuf}, - process::Command, }; use constants::PLUGINS; @@ -13,9 +16,6 @@ use oxc_tasks_common::{normalize_path, project_root, Snapshot}; use test_case::TestCaseKind; use walkdir::WalkDir; -mod driver; -mod test_case; - #[test] #[cfg(any(coverage, coverage_nightly))] fn test() { @@ -63,17 +63,6 @@ const OXC_CONFORMANCE_SNAPSHOT: &str = "oxc.snap.md"; const EXEC_SNAPSHOT: &str = "babel_exec.snap.md"; const OXC_EXEC_SNAPSHOT: &str = "oxc_exec.snap.md"; -struct SnapshotOption { - paths: IndexMap>, - dest: PathBuf, -} - -impl SnapshotOption { - fn new(paths: IndexMap>, file_name: &'static str) -> Self { - Self { paths, dest: snap_root().join(file_name) } - } -} - impl TestRunner { pub fn new(options: TestRunnerOptions) -> Self { let snapshot = Snapshot::new(&babel_root(), /* show_commit */ true); @@ -88,14 +77,15 @@ impl TestRunner { ] { let (transform_paths, exec_files) = Self::glob_files(root, self.options.filter.as_ref()); - self.generate_snapshot(root, SnapshotOption::new(transform_paths, snapshot)); + self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); if self.options.exec && !exec_files.is_empty() { let fixture_root = fixture_root(); let _ = fs::remove_dir_all(&fixture_root); let _ = fs::create_dir(&fixture_root); - self.generate_snapshot(root, SnapshotOption::new(exec_files, exec_snapshot)); - self.run_vitest(&SnapshotOption::new(IndexMap::default(), exec_snapshot)); + let dest = snap_root().join(exec_snapshot); + self.generate_snapshot(root, &dest, exec_files); + self.run_vitest(&dest); } } } @@ -140,8 +130,12 @@ impl TestRunner { (transform_files, exec_files) } - fn generate_snapshot(&self, root: &Path, option: SnapshotOption) { - let SnapshotOption { paths, dest } = option; + fn generate_snapshot( + &self, + root: &Path, + dest: &Path, + paths: IndexMap>, + ) { let mut snapshot = String::new(); let mut total = 0; let mut all_passed = vec![]; @@ -194,32 +188,7 @@ impl TestRunner { let snapshot = format!( "Passed: {all_passed_count}/{total}\n\n# All Passed:\n{all_passed}\n\n\n{snapshot}" ); - self.snapshot.save(&dest, &snapshot); + self.snapshot.save(dest, &snapshot); } } - - fn run_vitest(&self, option: &SnapshotOption) { - let version = String::from("node: ") - + &String::from_utf8(Command::new("node").arg("--version").output().unwrap().stdout) - .unwrap(); - let output = Command::new("node") - .current_dir(conformance_root()) - .env("NO_COLOR", "1") - .args([ - "--run", - "vitest", - "--", - "run", - "--reporter=basic", - "--exclude=\"\"", - "--no-color", - "./fixtures", - ]) - .output() - .unwrap(); - let content = if output.stderr.is_empty() { output.stdout } else { output.stderr }; - let output = String::from_utf8(content).unwrap(); - let output = version + &output; - self.snapshot.save(&option.dest, &output); - } } From 58db9ef32216fa09bd75a0b29429a0060edfe83d Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:31:52 +0000 Subject: [PATCH 042/121] refactor(codegen): do not print unnecessary parentheses if both sides use the same logical operator (#7325) As shown by the changing tests, we don't need to print parentheses for them. ### Comparison In [esbuild](https://esbuild.github.io/try/#dAAwLjI0LjAAAGEgPz8gKGIgPz8gKGMgPz8gZCkpOwooYSA/PyAoYiA/PyAoYyA/PyBkKSkpOwooYSB8fCAoYiB8fCBjKSkgfHwgZDsKYSB8fCAoYiB8fCAoYyB8fCBkKSk7CmEgJiYgKChiICYmIGMpICYmIGQp), it will print parentheses as-is, in [SWC](https://play.swc.rs/?version=1.9.2&code=H4sIAAAAAAAAA0tUsLdX0EgCk8kgMkVT05pLIxGLMES8pgYkDiSTNTVBVIo1F5IgUDFIDKQ2UUFNTUEDKAykkjVBZIomAGEbiHtuAAAA&config=H4sIAAAAAAAAA1VQzW7DIAy%2B9ykin6tlyrHXTb3ttCdA1GmpACPbSIuqvPuAJml6w9%2Bv8ePQdXAXC6fuUZ5lSIYFeZsLIlNU81cQ0CmhWHZJ4biyKpVSztiQ%2BUmAGr6iVhPK8DkMsOJsoozEYd%2BQBb9xdBHPxF%2FeiJwd%2BossuVsVo7G68xXIhUSsv5TZYi27qSY59T1K%2BJBbn56W48vAOaoLTWuyUjDqLCz0%2FPYDTyRVNxovyw4QXHTjtF%2FdUiglIu%2FCKjXx6jf%2FYc1v6RDokhu5HL0etq5U0gLFu8BLuTZu6eDkZ7W3s8%2F%2FYy0r4MUBAAA%3D), we have the same output now --- crates/oxc_codegen/src/binary_expr_visitor.rs | 16 ++++++++++++++-- crates/oxc_codegen/tests/integration/unit.rs | 10 +++++----- tasks/minsize/minsize.snap | 8 ++++---- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/crates/oxc_codegen/src/binary_expr_visitor.rs b/crates/oxc_codegen/src/binary_expr_visitor.rs index ca4b22527a37a8..f5417ad4883c3f 100644 --- a/crates/oxc_codegen/src/binary_expr_visitor.rs +++ b/crates/oxc_codegen/src/binary_expr_visitor.rs @@ -46,6 +46,12 @@ pub enum BinaryishOperator { Logical(LogicalOperator), } +impl BinaryishOperator { + fn is_binary(self) -> bool { + matches!(self, Self::Binary(_)) + } +} + fn print_binary_operator(op: BinaryOperator, p: &mut Codegen) { let operator = op.as_str(); if op.is_keyword() { @@ -148,9 +154,15 @@ impl<'a> BinaryExpressionVisitor<'a> { pub fn check_and_prepare(&mut self, p: &mut Codegen) -> bool { let e = self.e; - self.operator = e.operator(); - self.wrap = self.precedence >= self.operator.precedence() + // We don't need to print parentheses if both sides use the same logical operator + // For example: `(a && b) && c` should be printed as `a && b && c` + // ^^ e.operator() ^^ self.operator + let precedence_check = self.precedence >= e.operator().precedence() + && (self.operator.is_binary() || self.precedence != self.operator.precedence()); + + self.operator = e.operator(); + self.wrap = precedence_check || (self.operator == BinaryishOperator::Binary(BinaryOperator::In) && self.ctx.intersects(Context::FORBID_IN)); diff --git a/crates/oxc_codegen/tests/integration/unit.rs b/crates/oxc_codegen/tests/integration/unit.rs index 2dc4bd1e7cd9d1..cbd077a4e25499 100644 --- a/crates/oxc_codegen/tests/integration/unit.rs +++ b/crates/oxc_codegen/tests/integration/unit.rs @@ -174,8 +174,8 @@ fn conditional() { fn coalesce() { test_minify("a ?? b", "a??b;"); test_minify("a ?? b ?? c ?? d", "a??b??c??d;"); - test_minify("a ?? (b ?? (c ?? d))", "a??(b??(c??d));"); - test_minify("(a ?? (b ?? (c ?? d)))", "a??(b??(c??d));"); + test_minify("a ?? (b ?? (c ?? d))", "a??b??c??d;"); + test_minify("(a ?? (b ?? (c ?? d)))", "a??b??c??d;"); test_minify("a, b ?? c", "a,b??c;"); test_minify("(a, b) ?? c", "(a,b)??c;"); test_minify("a, b ?? c, d", "a,b??c,d;"); @@ -188,8 +188,8 @@ fn coalesce() { #[test] fn logical_or() { test_minify("a || b || c", "a||b||c;"); - test_minify("(a || (b || c)) || d", "a||(b||c)||d;"); - test_minify("a || (b || (c || d))", "a||(b||(c||d));"); + test_minify("(a || (b || c)) || d", "a||b||c||d;"); + test_minify("a || (b || (c || d))", "a||b||c||d;"); test_minify("a || b && c", "a||b&&c;"); test_minify("(a || b) && c", "(a||b)&&c;"); test_minify("a, b || c, d", "a,b||c,d;"); @@ -201,7 +201,7 @@ fn logical_or() { #[test] fn logical_and() { test_minify("a && b && c", "a&&b&&c;"); - test_minify("a && ((b && c) && d)", "a&&(b&&c&&d);"); + test_minify("a && ((b && c) && d)", "a&&b&&c&&d;"); test_minify("((a && b) && c) && d", "a&&b&&c&&d;"); test_minify("(a || b) && (c || d)", "(a||b)&&(c||d);"); test_minify("a, b && c, d", "a,b&&c,d;"); diff --git a/tasks/minsize/minsize.snap b/tasks/minsize/minsize.snap index 375432cb7a48d6..3b04256db6ca84 100644 --- a/tasks/minsize/minsize.snap +++ b/tasks/minsize/minsize.snap @@ -10,17 +10,17 @@ Original | Minified | esbuild | Gzip | esbuild 544.10 kB | 73.48 kB | 72.48 kB | 26.12 kB | 26.20 kB | lodash.js -555.77 kB | 276.49 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js +555.77 kB | 276.48 kB | 270.13 kB | 91.15 kB | 90.80 kB | d3.js -1.01 MB | 467.60 kB | 458.89 kB | 126.74 kB | 126.71 kB | bundle.min.js +1.01 MB | 467.59 kB | 458.89 kB | 126.73 kB | 126.71 kB | bundle.min.js 1.25 MB | 662.86 kB | 646.76 kB | 164.00 kB | 163.73 kB | three.js -2.14 MB | 741.57 kB | 724.14 kB | 181.45 kB | 181.07 kB | victory.js +2.14 MB | 741.55 kB | 724.14 kB | 181.45 kB | 181.07 kB | victory.js 3.20 MB | 1.02 MB | 1.01 MB | 332.01 kB | 331.56 kB | echarts.js 6.69 MB | 2.39 MB | 2.31 MB | 496.10 kB | 488.28 kB | antd.js -10.95 MB | 3.56 MB | 3.49 MB | 911.23 kB | 915.50 kB | typescript.js +10.95 MB | 3.56 MB | 3.49 MB | 911.24 kB | 915.50 kB | typescript.js From 6cfb5df9b9d1dc93287cfae14a9e2bfecf476c34 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:31:54 +0000 Subject: [PATCH 043/121] feat(transformer): support generate proper binding name from ChainExpression (#7326) --- .../src/ast_operations/gather_node_parts.rs | 16 ++++++++++++++++ .../coverage/snapshots/semantic_typescript.snap | 6 +++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs index aa4ef25cf7aa80..3c0d730561f813 100644 --- a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs +++ b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs @@ -186,6 +186,7 @@ impl<'a> GatherNodeParts<'a> for Expression<'a> { Self::ParenthesizedExpression(expr) => expr.gather(f), Self::UnaryExpression(expr) => expr.gather(f), Self::UpdateExpression(expr) => expr.gather(f), + Self::ChainExpression(expr) => expr.gather(f), Self::MetaProperty(expr) => expr.gather(f), Self::JSXElement(expr) => expr.gather(f), Self::JSXFragment(expr) => expr.gather(f), @@ -198,6 +199,21 @@ impl<'a> GatherNodeParts<'a> for Expression<'a> { } } +impl<'a> GatherNodeParts<'a> for ChainExpression<'a> { + fn gather(&self, f: &mut F) { + self.expression.gather(f); + } +} + +impl<'a> GatherNodeParts<'a> for ChainElement<'a> { + fn gather(&self, f: &mut F) { + match self { + ChainElement::CallExpression(expr) => expr.gather(f), + expr => expr.to_member_expression().gather(f), + } + } +} + impl<'a> GatherNodeParts<'a> for MemberExpression<'a> { fn gather(&self, f: &mut F) { match self { diff --git a/tasks/coverage/snapshots/semantic_typescript.snap b/tasks/coverage/snapshots/semantic_typescript.snap index 424fec9b495307..6a630dc2064918 100644 --- a/tasks/coverage/snapshots/semantic_typescript.snap +++ b/tasks/coverage/snapshots/semantic_typescript.snap @@ -47454,11 +47454,11 @@ rebuilt : ScopeId(0): [] tasks/coverage/typescript/tests/cases/conformance/expressions/nullishCoalescingOperator/nullishCoalescingOperator12.ts semantic error: Bindings mismatch: after transform: ScopeId(0): ["obj"] -rebuilt : ScopeId(0): ["_ref", "obj"] +rebuilt : ScopeId(0): ["_obj$arr", "obj"] Bindings mismatch: -after transform: ScopeId(1): ["_ref", "i"] +after transform: ScopeId(1): ["_obj$arr", "i"] rebuilt : ScopeId(1): ["i"] -Symbol scope ID mismatch for "_ref": +Symbol scope ID mismatch for "_obj$arr": after transform: SymbolId(2): ScopeId(1) rebuilt : SymbolId(0): ScopeId(0) From d0e64fd80a707d19f0e7edfe34018e176c8ad3e5 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 10:52:42 +0000 Subject: [PATCH 044/121] refactor(transform_conformance): remove `TestCase` trait (#7356) --- tasks/transform_conformance/src/lib.rs | 33 ++- tasks/transform_conformance/src/test_case.rs | 214 ++++++------------- 2 files changed, 76 insertions(+), 171 deletions(-) diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index 3620ec70f2af6e..7d5a1160f3bfc0 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -13,7 +13,7 @@ use std::{ use constants::PLUGINS; use indexmap::IndexMap; use oxc_tasks_common::{normalize_path, project_root, Snapshot}; -use test_case::TestCaseKind; +use test_case::{TestCase, TestCaseKind}; use walkdir::WalkDir; #[test] @@ -93,15 +93,15 @@ impl TestRunner { fn glob_files( root: &Path, filter: Option<&String>, - ) -> (IndexMap>, IndexMap>) { + ) -> (IndexMap>, IndexMap>) { let cwd = root.parent().unwrap_or(root); // use `IndexMap` to keep the order of the test cases the same in insert order. - let mut transform_files = IndexMap::>::new(); - let mut exec_files = IndexMap::>::new(); + let mut transform_files = IndexMap::>::new(); + let mut exec_files = IndexMap::>::new(); for case in PLUGINS { let root = root.join(case).join("test/fixtures"); - let (mut transform_paths, mut exec_paths): (Vec, Vec) = + let (mut transform_paths, mut exec_paths): (Vec, Vec) = WalkDir::new(root) .into_iter() .filter_map(Result::ok) @@ -112,12 +112,12 @@ impl TestRunner { return None; } } - TestCaseKind::new(cwd, path).filter(|test_case| !test_case.skip_test_case()) + TestCase::new(cwd, path).filter(|test_case| !test_case.skip_test_case()) }) - .partition(|p| matches!(p, TestCaseKind::Transform(_))); + .partition(|case| case.kind == TestCaseKind::Conformance); - transform_paths.sort_unstable_by(|a, b| a.path().cmp(b.path())); - exec_paths.sort_unstable_by(|a, b| a.path().cmp(b.path())); + transform_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); + exec_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); if !transform_paths.is_empty() { transform_files.insert((*case).to_string(), transform_paths); @@ -130,12 +130,7 @@ impl TestRunner { (transform_files, exec_files) } - fn generate_snapshot( - &self, - root: &Path, - dest: &Path, - paths: IndexMap>, - ) { + fn generate_snapshot(&self, root: &Path, dest: &Path, paths: IndexMap>) { let mut snapshot = String::new(); let mut total = 0; let mut all_passed = vec![]; @@ -147,13 +142,13 @@ impl TestRunner { total += num_of_tests; // Run the test - let (passed, failed): (Vec, Vec) = test_cases + let (passed, failed): (Vec, Vec) = test_cases .into_iter() .map(|mut test_case| { test_case.test(self.options.filter.is_some()); test_case }) - .partition(|test_case| test_case.errors().is_empty()); + .partition(|test_case| test_case.errors.is_empty()); all_passed_count += passed.len(); // Snapshot @@ -166,9 +161,9 @@ impl TestRunner { for test_case in failed { snapshot.push_str("* "); snapshot.push_str(&normalize_path( - test_case.path().strip_prefix(&case_root).unwrap(), + test_case.path.strip_prefix(&case_root).unwrap(), )); - let errors = test_case.errors(); + let errors = test_case.errors; if !errors.is_empty() { snapshot.push('\n'); for error in errors { diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index d9105e6a9214f5..3b8063826c28c3 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -22,83 +22,54 @@ use crate::{ }; #[derive(Debug)] +pub struct TestCase { + pub kind: TestCaseKind, + pub path: PathBuf, + pub options: BabelOptions, + pub transform_options: Result>, + pub errors: Vec, +} + +#[derive(Debug, Clone, Copy, Eq, PartialEq)] pub enum TestCaseKind { - Transform(ConformanceTestCase), - Exec(ExecTestCase), + Conformance, + Exec, } -impl TestCaseKind { +impl TestCase { pub fn new(cwd: &Path, path: &Path) -> Option { + let mut options = BabelOptions::from_test_path(path.parent().unwrap()); + options.cwd.replace(cwd.to_path_buf()); + let transform_options = TransformOptions::try_from(&options); + let path = path.to_path_buf(); + let errors = vec![]; + // in `exec` directory - if path.parent().is_some_and(|path| path.file_name().is_some_and(|n| n == "exec")) - && path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap())) + let kind = if path + .extension() + .is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap())) + && (path.parent().is_some_and(|path| path.file_name().is_some_and(|n| n == "exec")) + || path.file_stem().is_some_and(|name| name == "exec")) { - return Some(Self::Exec(ExecTestCase::new(cwd, path))); + TestCaseKind::Exec } - // named `exec.[ext]` - if path.file_stem().is_some_and(|name| name == "exec") - && path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap())) - { - return Some(Self::Exec(ExecTestCase::new(cwd, path))); - } - // named `input.[ext]` or `input.d.ts` - if (path.file_stem().is_some_and(|name| name == "input") + else if (path.file_stem().is_some_and(|name| name == "input") && path .extension() .is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))) || path.file_name().is_some_and(|name| name == "input.d.ts") { - return Some(Self::Transform(ConformanceTestCase::new(cwd, path))); - } + TestCaseKind::Conformance + } else { + return None; + }; - None + Some(Self { kind, path, options, transform_options, errors }) } pub fn skip_test_case(&self) -> bool { - match self { - Self::Transform(test_case) => test_case.skip_test_case(), - Self::Exec(exec_case) => exec_case.skip_test_case(), - } - } - - pub fn path(&self) -> &Path { - match self { - Self::Transform(test_case) => &test_case.path, - Self::Exec(exec_case) => &exec_case.path, - } - } - - pub fn test(&mut self, filter: bool) { - match self { - Self::Transform(test_case) => test_case.test(filter), - Self::Exec(test_case) => test_case.test(filter), - } - } - - pub fn errors(&self) -> &Vec { - match self { - Self::Transform(test_case) => test_case.errors(), - Self::Exec(test_case) => test_case.errors(), - } - } -} - -pub trait TestCase { - fn new(cwd: &Path, path: &Path) -> Self; - - fn options(&self) -> &BabelOptions; - - fn transform_options(&self) -> &Result>; - - fn test(&mut self, filtered: bool); - - fn errors(&self) -> &Vec; - - fn path(&self) -> &Path; - - fn skip_test_case(&self) -> bool { - let options = self.options(); + let options = &self.options; // Skip plugins we don't support yet if PLUGINS_NOT_SUPPORTED_YET @@ -111,7 +82,7 @@ pub trait TestCase { if let Some(b) = options.babel_8_breaking { if b { // Skip deprecated react options - if self.transform_options().as_ref().is_ok_and(|options| { + if self.transform_options.as_ref().is_ok_and(|options| { options.jsx.use_built_ins.is_some() || options.jsx.use_spread.is_some() }) { return true; @@ -133,7 +104,7 @@ pub trait TestCase { } // Skip some Babel tests. - if let Ok(path) = self.path().strip_prefix(packages_root()) { + if let Ok(path) = self.path.strip_prefix(packages_root()) { // babel skip test cases that in a directory starting with a dot // https://github.com/babel/babel/blob/0effd92d886b7135469d23612ceba6414c721673/packages/babel-helper-fixtures/src/index.ts#L223 if path.components().any(|c| c.as_os_str().to_str().unwrap().starts_with('.')) { @@ -146,7 +117,7 @@ pub trait TestCase { } } - let dir = self.path().parent().unwrap(); + let dir = self.path.parent().unwrap(); // Skip custom plugin.js if dir.join("plugin.js").exists() { return true; @@ -161,7 +132,7 @@ pub trait TestCase { } fn transform(&self, path: &Path) -> Result { - let transform_options = match self.transform_options() { + let transform_options = match &self.transform_options { Ok(transform_options) => transform_options, Err(json_err) => { return Err(OxcDiagnostic::error(format!("{json_err:?}"))); @@ -173,8 +144,8 @@ pub trait TestCase { // Some babel test cases have a js extension, but contain typescript code. // Therefore, if the typescript plugin exists, enable typescript. let source_type = SourceType::from_path(path).unwrap().with_typescript( - self.options().plugins.syntax_typescript.is_some() - || self.options().plugins.typescript.is_some(), + self.options.plugins.syntax_typescript.is_some() + || self.options.plugins.typescript.is_some(), ); let mut options = transform_options.clone(); @@ -182,42 +153,16 @@ pub trait TestCase { let driver = Driver::new(false, options).execute(&source_text, source_type, path); Ok(driver) } -} - -#[derive(Debug)] -pub struct ConformanceTestCase { - path: PathBuf, - options: BabelOptions, - transform_options: Result>, - errors: Vec, -} - -impl TestCase for ConformanceTestCase { - fn new(cwd: &Path, path: &Path) -> Self { - let mut options = BabelOptions::from_test_path(path.parent().unwrap()); - options.cwd.replace(cwd.to_path_buf()); - let transform_options = TransformOptions::try_from(&options); - Self { path: path.to_path_buf(), options, transform_options, errors: vec![] } - } - - fn options(&self) -> &BabelOptions { - &self.options - } - - fn transform_options(&self) -> &Result> { - &self.transform_options - } - - fn path(&self) -> &Path { - &self.path - } - fn errors(&self) -> &Vec { - &self.errors + pub fn test(&mut self, filtered: bool) { + match self.kind { + TestCaseKind::Conformance => self.test_conformance(filtered), + TestCaseKind::Exec => self.test_exec(filtered), + } } /// Test conformance by comparing the parsed babel code and transformed code. - fn test(&mut self, filtered: bool) { + fn test_conformance(&mut self, filtered: bool) { let output_path = self.path.parent().unwrap().read_dir().unwrap().find_map(|entry| { let path = entry.ok()?.path(); let file_stem = path.file_stem()?; @@ -259,7 +204,7 @@ impl TestCase for ConformanceTestCase { let mut actual_errors = None; let mut transform_options = None; - match self.transform_options() { + match &self.transform_options { Err(json_err) => { let error = json_err.iter().map(ToString::to_string).collect::>().join("\n"); actual_errors.replace(get_babel_error(&error)); @@ -285,7 +230,7 @@ impl TestCase for ConformanceTestCase { } } - let babel_options = self.options(); + let babel_options = &self.options; let output; let passed = if let Some(throws) = &babel_options.throws { @@ -372,17 +317,25 @@ impl TestCase for ConformanceTestCase { self.errors.push(OxcDiagnostic::error(actual_errors)); } } -} -#[derive(Debug)] -pub struct ExecTestCase { - path: PathBuf, - options: BabelOptions, - transform_options: Result>, - errors: Vec, -} + fn test_exec(&mut self, filtered: bool) { + if filtered { + println!("input_path: {:?}", &self.path); + println!("Input:\n{}\n", fs::read_to_string(&self.path).unwrap()); + } + + let result = match self.transform(&self.path) { + Ok(mut driver) => driver.printed(), + Err(error) => { + if filtered { + println!("Transform Errors:\n{error:?}\n",); + } + return; + } + }; + self.write_to_test_files(&result); + } -impl ExecTestCase { fn write_to_test_files(&self, content: &str) { let unprefixed_path = self .path @@ -424,49 +377,6 @@ test("exec", () => {{ } } -impl TestCase for ExecTestCase { - fn new(cwd: &Path, path: &Path) -> Self { - let mut options = BabelOptions::from_test_path(path.parent().unwrap()); - options.cwd.replace(cwd.to_path_buf()); - let transform_options = TransformOptions::try_from(&options); - Self { path: path.to_path_buf(), options, transform_options, errors: vec![] } - } - - fn options(&self) -> &BabelOptions { - &self.options - } - - fn transform_options(&self) -> &Result> { - &self.transform_options - } - - fn path(&self) -> &Path { - &self.path - } - - fn errors(&self) -> &Vec { - &self.errors - } - - fn test(&mut self, filtered: bool) { - if filtered { - println!("input_path: {:?}", &self.path); - println!("Input:\n{}\n", fs::read_to_string(&self.path).unwrap()); - } - - let result = match self.transform(&self.path) { - Ok(mut driver) => driver.printed(), - Err(error) => { - if filtered { - println!("Transform Errors:\n{error:?}\n",); - } - return; - } - }; - self.write_to_test_files(&result); - } -} - fn get_babel_error(error: &str) -> String { match error { "transform-react-jsx: unknown variant `invalidOption`, expected `classic` or `automatic`" => "Runtime must be either \"classic\" or \"automatic\".", From 84f3bf2f976d09b494df4512917fb72aab8b06f5 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:22:42 +0000 Subject: [PATCH 045/121] refactor(transform_conformance): clean up test execution code (#7357) --- .../snapshots/babel.snap.md | 209 +----------------- .../snapshots/babel_exec.snap.md | 96 +++----- .../snapshots/oxc_exec.snap.md | 10 +- tasks/transform_conformance/src/constants.rs | 3 + tasks/transform_conformance/src/lib.rs | 75 +++---- tasks/transform_conformance/src/test_case.rs | 138 ++++++------ 6 files changed, 151 insertions(+), 380 deletions(-) diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 19eea87d11d7ff..4068272f73e7b0 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -1,6 +1,6 @@ commit: d20b314c -Passed: 319/633 +Passed: 327/574 # All Passed: * babel-plugin-transform-class-static-block @@ -296,170 +296,6 @@ x Output mismatch x Output mismatch -# babel-plugin-transform-object-rest-spread (5/59) -* assumption-ignoreFunctionLength/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-assignment-expression/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-computed/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-nested/input.js -x Output mismatch - -* assumption-objectRestNoSymbols/rest-var-declaration/input.js -x Output mismatch - -* assumption-pureGetters/rest-remove-unused-excluded-keys/input.js -x Output mismatch - -* assumption-pureGetters/spread-single-call/input.js -x Output mismatch - -* assumption-setSpreadProperties/assignment/input.js -x Output mismatch - -* assumption-setSpreadProperties/expression/input.js -x Output mismatch - -* assumption-setSpreadProperties/targets-support-object-assign/input.js -x Output mismatch - -* assumption-setSpreadProperties-with-useBuiltIns/assignment/input.js -x Output mismatch - -* assumption-setSpreadProperties-with-useBuiltIns/expression/input.js -x Output mismatch - -* object-rest/assignment-expression/input.js -x Output mismatch - -* object-rest/catch-clause/input.js -x Output mismatch - -* object-rest/duplicate-decl-bug/input.js -x Output mismatch - -* object-rest/export/input.mjs -x Output mismatch - -* object-rest/for-x/input.js -x Output mismatch - -* object-rest/for-x-array-pattern/input.js -x Output mismatch - -* object-rest/for-x-completion-record/input.js -x Output mismatch - -* object-rest/impure-computed/input.js -x Output mismatch - -* object-rest/nested/input.js -x Output mismatch - -* object-rest/nested-2/input.js -x Output mismatch - -* object-rest/nested-array/input.js -x Output mismatch - -* object-rest/nested-array-2/input.js -x Output mismatch - -* object-rest/nested-computed-key/input.js -x Output mismatch - -* object-rest/nested-default-value/input.js -x Output mismatch - -* object-rest/nested-literal-property/input.js -x Output mismatch - -* object-rest/nested-order/input.js -x Output mismatch - -* object-rest/non-string-computed/input.js -x Output mismatch - -* object-rest/null-destructuring/input.js -x Output mismatch - -* object-rest/object-ref-computed/input.js -x Output mismatch - -* object-rest/parameters/input.js -x Output mismatch - -* object-rest/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* object-rest/remove-unused-excluded-keys-loose/input.js -x Output mismatch - -* object-rest/symbol/input.js -x Output mismatch - -* object-rest/template-literal-allLiterals-true-no-hoisting/input.js -x Output mismatch - -* object-rest/template-literal-property-allLiterals-false/input.js -x Output mismatch - -* object-rest/template-literal-property-allLiterals-true/input.js -x Output mismatch - -* object-rest/variable-destructuring/input.js -x Output mismatch - -* object-rest/with-array-rest/input.js -x Output mismatch - -* object-spread/expression/input.js -x Output mismatch - -* object-spread/side-effect/input.js -x Output mismatch - -* object-spread-loose/assignment/input.js -x Output mismatch - -* object-spread-loose/expression/input.js -x Output mismatch - -* object-spread-loose/parameters-object-rest-used-in-default/input.js -x Output mismatch - -* object-spread-loose/side-effect/input.js -x Output mismatch - -* object-spread-loose/variable-declaration/input.js -x Output mismatch - -* object-spread-loose-builtins/expression/input.js -x Output mismatch - -* object-spread-loose-builtins/side-effect/input.js -x Output mismatch - -* regression/gh-4904/input.js -x Output mismatch - -* regression/gh-5151/input.js -x Output mismatch - -* regression/gh-7304/input.mjs -x Output mismatch - -* regression/gh-7388/input.js -x Output mismatch - -* regression/gh-8323/input.js -x Output mismatch - - # babel-plugin-transform-async-to-generator (11/28) * assumption-ignoreFunctionLength-true/basic/input.mjs x Output mismatch @@ -572,7 +408,7 @@ rebuilt : ScopeId(1): [] x Output mismatch -# babel-plugin-transform-typescript (43/155) +# babel-plugin-transform-typescript (45/155) * cast/as-expression/input.ts Unresolved references mismatch: after transform: ["T", "x"] @@ -1206,12 +1042,6 @@ Unresolved reference IDs mismatch for "LongNameModule": after transform: [ReferenceId(1), ReferenceId(5)] rebuilt : [ReferenceId(1)] -* namespace/ambient-module-nested/input.ts -Ambient modules cannot be nested in other modules or namespaces. - -* namespace/ambient-module-nested-exported/input.ts -Ambient modules cannot be nested in other modules or namespaces. - * namespace/clobber-class/input.ts Missing SymbolId: "_A" Missing ReferenceId: "_A" @@ -2167,31 +1997,10 @@ after transform: ["T", "f"] rebuilt : ["f"] -# babel-plugin-transform-react-jsx (124/145) +# babel-plugin-transform-react-jsx (135/145) * autoImport/after-polyfills-compiled-to-cjs/input.mjs x Output mismatch -* pure/false-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/false-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/true-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/true-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/unset-pragma-comment-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* pure/unset-pragma-option-automatic-runtime/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - -* react/should-disallow-spread-children/input.js -Spread children are not supported in React. - * react/should-disallow-valueless-key/input.js ! Please provide an explicit key value. Using "key" as a shorthand for @@ -2225,18 +2034,9 @@ Spread children are not supported in React. `---- -* react/should-warn-when-importSource-is-set/input.js -importSource cannot be set when runtime is classic. - -* react/should-warn-when-importSource-pragma-is-set/input.js -importSource cannot be set when runtime is classic. - * react-automatic/does-not-add-source-self-automatic/input.mjs transform-react-jsx: unknown field `autoImport`, expected one of `runtime`, `development`, `throwIfNamespace`, `pure`, `importSource`, `pragma`, `pragmaFrag`, `useBuiltIns`, `useSpread`, `refresh` -* react-automatic/should-disallow-spread-children/input.js -Spread children are not supported in React. - * react-automatic/should-disallow-valueless-key/input.js ! Please provide an explicit key value. Using "key" as a shorthand for @@ -2270,9 +2070,6 @@ Spread children are not supported in React. `---- -* react-automatic/should-warn-when-pragma-or-pragmaFrag-is-set/input.js -pragma and pragmaFrag cannot be set when runtime is automatic. - * spread-transform/transform-to-babel-extend/input.js x Output mismatch diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index 293b58bda7efca..2509860738acc5 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -11,9 +11,9 @@ Error: 'eval' and 'arguments' cannot be used as a binding identifier in strict m ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52319:11 ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:51917:72 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/12]⎯ -⎯⎯⎯⎯⎯⎯ Failed Tests 13 ⎯⎯⎯⎯⎯⎯⎯ +⎯⎯⎯⎯⎯⎯ Failed Tests 11 ⎯⎯⎯⎯⎯⎯⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-objectRestNoSymbols-rest-ignore-symbols-exec.test.js > exec AssertionError: expected true to be false // Object.is equality @@ -31,7 +31,7 @@ AssertionError: expected true to be false // Object.is equality | ^ 13| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-rest-remove-unused-excluded-keys-exec.test.js > exec AssertionError: expected true to be false // Object.is equality @@ -49,7 +49,7 @@ AssertionError: expected true to be false // Object.is equality | ^ 11| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js > exec AssertionError: expected { foo: +0, middle: 1, bar: 1 } to deeply equal { foo: +0, middle: +0, bar: 1 } @@ -64,39 +64,39 @@ AssertionError: expected { foo: +0, middle: 1, bar: 1 } to deeply equal { foo: + + "middle": 1, } - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js:12:14 - 10| } }; - 11| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… - 12| expect(res).toEqual({ + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js:13:14 + 11| } }; + 12| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… + 13| expect(res).toEqual({ | ^ - 13| foo: 0, - 14| middle: 0, + 14| foo: 0, + 15| middle: 0, -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js > exec AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js:13:5 - 11| expect(() => { - 12| const objSpread = _objectSpread({}, obj); - 13| }).toThrow(); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js:14:5 + 12| expect(() => { + 13| const objSpread = _objectSpread({}, obj); + 14| }).toThrow(); | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { + 15| const obj2 = { "NOWRITE": 456 }; + 16| expect(() => { -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js > exec AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js:13:5 - 11| expect(() => { - 12| const objSpread = _objectSpread({}, obj); - 13| }).toThrow(); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js:14:5 + 12| expect(() => { + 13| const objSpread = _objectSpread({}, obj); + 14| }).toThrow(); | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { + 15| const obj2 = { "NOWRITE": 456 }; + 16| expect(() => { -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js > exec AssertionError: expected [ 1, 2 ] to deeply equal [ 1 ] @@ -109,14 +109,14 @@ AssertionError: expected [ 1, 2 ] to deeply equal [ 1 ] + 2, ] - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js:10:14 - 8| log.push(2); - 9| } }); - 10| expect(log).toEqual([1]); + ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js:11:14 + 9| log.push(2); + 10| } }); + 11| expect(log).toEqual([1]); | ^ - 11| }) + 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-builtins-side-effect-exec.test.js > exec AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } @@ -138,7 +138,7 @@ AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } 10| a: 2, 11| b: 1 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/12]⎯ FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-side-effect-exec.test.js > exec AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } @@ -160,31 +160,7 @@ AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } 10| a: 2, 11| b: 1 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/14]⎯ - - FAIL fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-basic-sample-exec.test.js > exec -ReferenceError: transformAsync is not defined - ❯ fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-basic-sample-exec.test.js:4:16 - 2| - 3| test("exec", () => { - 4| var actualP = transformAsync("var x = ", Object.assign({},… - | ^ - 5| var expected = ` - 6| var _jsxFileName = "/fake/path/mock.js"; - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/14]⎯ - - FAIL fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-with-source-exec.test.js > exec -ReferenceError: transformAsync is not defined - ❯ fixtures/babel-plugin-transform-react-jsx-source-test-fixtures-react-source-with-source-exec.test.js:4:16 - 2| - 3| test("exec", () => { - 4| var actualP = transformAsync("var x = … - | ^ - 5| var expected = "var x = ;"; - 6| return actualP.then((actual) => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-plugins-integration-issue-15170-exec.test.js > exec AssertionError: expected [Function] to not throw an error but 'ReferenceError: x is not defined' was thrown @@ -202,7 +178,7 @@ undefined | ^ 7| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js > exec TypeError: Assignment to constant variable. @@ -213,7 +189,7 @@ TypeError: Assignment to constant variable. | ^ 6| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[13/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/12]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js > exec AssertionError: expected false to be true // Object.is equality @@ -232,5 +208,5 @@ AssertionError: expected false to be true // Object.is equality 11| expect(/hello.world/su.test(input)).toBe(true); 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[14/14]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/12]⎯ diff --git a/tasks/transform_conformance/snapshots/oxc_exec.snap.md b/tasks/transform_conformance/snapshots/oxc_exec.snap.md index 3c698c22b65272..292cdaf7be6a0b 100644 --- a/tasks/transform_conformance/snapshots/oxc_exec.snap.md +++ b/tasks/transform_conformance/snapshots/oxc_exec.snap.md @@ -1,8 +1,8 @@ commit: d20b314c -Passed: 0/0 - -# All Passed: - - +node: v22.11.0 +filter: fixtures +include: **/*.{test,spec}.?(c|m)[jt]s?(x) +exclude: **/node_modules/**, **/dist/**, **/cypress/**, **/.{idea,git,cache,output,temp}/**, **/{karma,rollup,webpack,vite,vitest,jest,ava,babel,nyc,cypress,tsup,build,eslint,prettier}.config.*, "" +No test files found, exiting with code 1 diff --git a/tasks/transform_conformance/src/constants.rs b/tasks/transform_conformance/src/constants.rs index 3eaf32940804f5..d88637b422ad95 100644 --- a/tasks/transform_conformance/src/constants.rs +++ b/tasks/transform_conformance/src/constants.rs @@ -102,3 +102,6 @@ pub const SKIP_TESTS: &[&str] = &[ "babel-preset-env/test/fixtures/debug", "babel-preset-env/test/fixtures/debug-babel-7", ]; + +pub const SNAPSHOT_TESTS: &[&str] = + &["babel-plugin-transform-object-rest-spread", "babel-plugin-transform-optional-chaining"]; diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index 7d5a1160f3bfc0..0453232095c9b1 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -75,59 +75,61 @@ impl TestRunner { (packages_root(), CONFORMANCE_SNAPSHOT, EXEC_SNAPSHOT), (oxc_test_root(), OXC_CONFORMANCE_SNAPSHOT, OXC_EXEC_SNAPSHOT), ] { - let (transform_paths, exec_files) = - Self::glob_files(root, self.options.filter.as_ref()); - self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); - - if self.options.exec && !exec_files.is_empty() { + if self.options.exec { let fixture_root = fixture_root(); let _ = fs::remove_dir_all(&fixture_root); let _ = fs::create_dir(&fixture_root); - let dest = snap_root().join(exec_snapshot); - self.generate_snapshot(root, &dest, exec_files); - self.run_vitest(&dest); + } + let transform_paths = Self::generate_test_cases(root, self.options.filter.as_ref()); + self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); + if self.options.exec { + self.run_vitest(&snap_root().join(exec_snapshot)); } } } - fn glob_files( + fn generate_test_cases( root: &Path, filter: Option<&String>, - ) -> (IndexMap>, IndexMap>) { + ) -> IndexMap> { let cwd = root.parent().unwrap_or(root); // use `IndexMap` to keep the order of the test cases the same in insert order. let mut transform_files = IndexMap::>::new(); - let mut exec_files = IndexMap::>::new(); for case in PLUGINS { let root = root.join(case).join("test/fixtures"); - let (mut transform_paths, mut exec_paths): (Vec, Vec) = - WalkDir::new(root) - .into_iter() - .filter_map(Result::ok) - .filter_map(|e| { - let path = e.path(); - if let Some(filter) = filter { - if !path.to_string_lossy().contains(filter) { - return None; - } + + let mut cases = WalkDir::new(root) + .into_iter() + .filter_map(Result::ok) + .filter(|e| { + if let Some(filter) = filter { + if !e.path().to_string_lossy().contains(filter) { + return false; } - TestCase::new(cwd, path).filter(|test_case| !test_case.skip_test_case()) - }) - .partition(|case| case.kind == TestCaseKind::Conformance); + } + true + }) + .filter_map(|e| TestCase::new(cwd, e.path())) + .filter(|test_case| !test_case.skip_test_case()) + .map(|mut case| { + case.test(filter.is_some()); + case + }) + .collect::>(); - transform_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); - exec_paths.sort_unstable_by(|a, b| a.path.cmp(&b.path)); + cases.sort_unstable_by(|a, b| a.path.cmp(&b.path)); - if !transform_paths.is_empty() { - transform_files.insert((*case).to_string(), transform_paths); - } - if !exec_paths.is_empty() { - exec_files.insert((*case).to_string(), exec_paths); + let transform_cases = cases + .into_iter() + .filter(|case| case.kind == TestCaseKind::Conformance) + .collect::>(); + if !transform_cases.is_empty() { + transform_files.insert((*case).to_string(), transform_cases); } } - (transform_files, exec_files) + transform_files } fn generate_snapshot(&self, root: &Path, dest: &Path, paths: IndexMap>) { @@ -142,13 +144,8 @@ impl TestRunner { total += num_of_tests; // Run the test - let (passed, failed): (Vec, Vec) = test_cases - .into_iter() - .map(|mut test_case| { - test_case.test(self.options.filter.is_some()); - test_case - }) - .partition(|test_case| test_case.errors.is_empty()); + let (passed, failed): (Vec, Vec) = + test_cases.into_iter().partition(|test_case| test_case.errors.is_empty()); all_passed_count += passed.len(); // Snapshot diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 3b8063826c28c3..8307faf9ae9c31 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -16,7 +16,7 @@ use oxc::{ use oxc_tasks_common::{normalize_path, print_diff_in_terminal, project_root}; use crate::{ - constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS}, + constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS, SNAPSHOT_TESTS}, driver::Driver, fixture_root, oxc_test_root, packages_root, }; @@ -25,8 +25,9 @@ use crate::{ pub struct TestCase { pub kind: TestCaseKind, pub path: PathBuf, - pub options: BabelOptions, - pub transform_options: Result>, + options: BabelOptions, + source_type: SourceType, + transform_options: Result>, pub errors: Vec, } @@ -34,6 +35,7 @@ pub struct TestCase { pub enum TestCaseKind { Conformance, Exec, + Snapshot, } impl TestCase { @@ -54,18 +56,44 @@ impl TestCase { TestCaseKind::Exec } // named `input.[ext]` or `input.d.ts` - else if (path.file_stem().is_some_and(|name| name == "input") - && path - .extension() - .is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap()))) - || path.file_name().is_some_and(|name| name == "input.d.ts") + else if path.file_stem().is_some_and(|name| name == "input" || name == "input.d") + && path.extension().is_some_and(|ext| VALID_EXTENSIONS.contains(&ext.to_str().unwrap())) { - TestCaseKind::Conformance + if path + .strip_prefix(packages_root()) + .is_ok_and(|p| SNAPSHOT_TESTS.iter().any(|t| p.to_string_lossy().starts_with(t))) + { + TestCaseKind::Snapshot + } else { + TestCaseKind::Conformance + } } else { return None; }; - Some(Self { kind, path, options, transform_options, errors }) + let source_type = Self::source_type(&path, &options); + + Some(Self { kind, path, options, source_type, transform_options, errors }) + } + + fn source_type(path: &Path, options: &BabelOptions) -> SourceType { + // Some babel test cases have a js extension, but contain typescript code. + // Therefore, if the typescript plugin exists, enable typescript. + let mut source_type = SourceType::from_path(path) + .unwrap() + .with_script(true) + .with_jsx(options.plugins.syntax_jsx); + source_type = match options.source_type.as_deref() { + Some("unambiguous") => source_type.with_unambiguous(true), + Some("script") => source_type.with_script(true), + Some("module") => source_type.with_module(true), + Some(s) => panic!("Unexpected source type {s}"), + None => source_type, + }; + source_type = source_type.with_typescript( + options.plugins.typescript.is_some() || options.plugins.syntax_typescript.is_some(), + ); + source_type } pub fn skip_test_case(&self) -> bool { @@ -131,33 +159,42 @@ impl TestCase { false } - fn transform(&self, path: &Path) -> Result { + fn transform(&self, mode: HelperLoaderMode) -> Result { + let path = &self.path; let transform_options = match &self.transform_options { Ok(transform_options) => transform_options, Err(json_err) => { - return Err(OxcDiagnostic::error(format!("{json_err:?}"))); + let error = json_err.iter().map(ToString::to_string).collect::>().join("\n"); + return Err(error); } }; let source_text = fs::read_to_string(path).unwrap(); - // Some babel test cases have a js extension, but contain typescript code. - // Therefore, if the typescript plugin exists, enable typescript. - let source_type = SourceType::from_path(path).unwrap().with_typescript( - self.options.plugins.syntax_typescript.is_some() - || self.options.plugins.typescript.is_some(), - ); - + let project_root = project_root(); let mut options = transform_options.clone(); - options.helper_loader.mode = HelperLoaderMode::Runtime; - let driver = Driver::new(false, options).execute(&source_text, source_type, path); - Ok(driver) + options.helper_loader.mode = mode; + let mut driver = Driver::new(false, options).execute(&source_text, self.source_type, path); + let errors = driver.errors(); + if !errors.is_empty() { + let source = NamedSource::new( + path.strip_prefix(project_root).unwrap().to_string_lossy(), + source_text.to_string(), + ); + return Err(errors + .into_iter() + .map(|err| format!("{:?}", err.with_source_code(source.clone()))) + .collect::>() + .join("\n")); + } + Ok(driver.printed()) } pub fn test(&mut self, filtered: bool) { match self.kind { TestCaseKind::Conformance => self.test_conformance(filtered), TestCaseKind::Exec => self.test_exec(filtered), + TestCaseKind::Snapshot => {} } } @@ -172,61 +209,22 @@ impl TestCase { let allocator = Allocator::default(); let input = fs::read_to_string(&self.path).unwrap(); - let source_type = { - let mut source_type = SourceType::from_path(&self.path) - .unwrap() - .with_script(true) - .with_jsx(self.options.plugins.syntax_jsx); - - source_type = match self.options.source_type.as_deref() { - Some("unambiguous") => source_type.with_unambiguous(true), - Some("script") => source_type.with_script(true), - Some("module") => source_type.with_module(true), - Some(s) => panic!("Unexpected source type {s}"), - None => source_type, - }; - - source_type = source_type.with_typescript( - self.options.plugins.typescript.is_some() - || self.options.plugins.syntax_typescript.is_some(), - ); - - source_type - }; - if filtered { println!("input_path: {:?}", &self.path); println!("output_path: {output_path:?}"); } - let project_root = project_root(); let mut transformed_code = String::new(); let mut actual_errors = None; let mut transform_options = None; - match &self.transform_options { - Err(json_err) => { - let error = json_err.iter().map(ToString::to_string).collect::>().join("\n"); + match self.transform(HelperLoaderMode::External) { + Err(error) => { actual_errors.replace(get_babel_error(&error)); } - Ok(options) => { - transform_options.replace(options.clone()); - let mut driver = - Driver::new(false, options.clone()).execute(&input, source_type, &self.path); - transformed_code = driver.printed(); - let errors = driver.errors(); - if !errors.is_empty() { - let source = NamedSource::new( - self.path.strip_prefix(project_root).unwrap().to_string_lossy(), - input.to_string(), - ); - let error = errors - .into_iter() - .map(|err| format!("{:?}", err.with_source_code(source.clone()))) - .collect::>() - .join("\n"); - actual_errors.replace(get_babel_error(&error)); - } + Ok(code) => { + transform_options.replace(self.transform_options.as_ref().unwrap().clone()); + transformed_code = code; } } @@ -243,7 +241,7 @@ impl TestCase { String::default, |output| { // Get expected code by parsing the source text, so we can get the same code generated result. - let ret = Parser::new(&allocator, &output, source_type) + let ret = Parser::new(&allocator, &output, self.source_type) .with_options(ParseOptions { // Related: async to generator, regression allow_return_outside_function: true, @@ -309,7 +307,7 @@ impl TestCase { if let Some(options) = transform_options { let mismatch_errors = Driver::new(/* check transform mismatch */ true, options) - .execute(&input, source_type, &self.path) + .execute(&input, self.source_type, &self.path) .errors(); self.errors.extend(mismatch_errors); } @@ -324,8 +322,8 @@ impl TestCase { println!("Input:\n{}\n", fs::read_to_string(&self.path).unwrap()); } - let result = match self.transform(&self.path) { - Ok(mut driver) => driver.printed(), + let result = match self.transform(HelperLoaderMode::Runtime) { + Ok(code) => code, Err(error) => { if filtered { println!("Transform Errors:\n{error:?}\n",); From d60801218e965eab40cd25201155a946d511122e Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 12:49:44 +0000 Subject: [PATCH 046/121] feat(transform_conformance): snapshot our transformed outputs (#7358) --- crates/oxc_transformer/src/options/env.rs | 12 +- .../snapshots/babel_exec.snap.md | 157 +----------------- tasks/transform_conformance/src/constants.rs | 2 +- tasks/transform_conformance/src/test_case.rs | 23 ++- 4 files changed, 28 insertions(+), 166 deletions(-) diff --git a/crates/oxc_transformer/src/options/env.rs b/crates/oxc_transformer/src/options/env.rs index ba159d7de7dc10..fc55a04c268cd1 100644 --- a/crates/oxc_transformer/src/options/env.rs +++ b/crates/oxc_transformer/src/options/env.rs @@ -7,7 +7,7 @@ use crate::{ es2015::{ArrowFunctionsOptions, ES2015Options}, es2016::ES2016Options, es2017::ES2017Options, - es2018::{ES2018Options, ObjectRestSpreadOptions}, + es2018::ES2018Options, es2019::ES2019Options, es2020::ES2020Options, es2021::ES2021Options, @@ -71,15 +71,7 @@ impl EnvOptions { }, es2016: ES2016Options { exponentiation_operator: true }, es2017: ES2017Options { async_to_generator: true }, - es2018: ES2018Options { - // Turned off because it is not ready. - object_rest_spread: if include_unfinished_plugins { - Some(ObjectRestSpreadOptions::default()) - } else { - None - }, - async_generator_functions: true, - }, + es2018: ES2018Options { object_rest_spread: None, async_generator_functions: true }, es2019: ES2019Options { optional_catch_binding: true }, es2020: ES2020Options { nullish_coalescing_operator: true, diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index 2509860738acc5..b38b07fced5656 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -11,156 +11,9 @@ Error: 'eval' and 'arguments' cannot be used as a binding identifier in strict m ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52319:11 ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:51917:72 -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/12]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯ -⎯⎯⎯⎯⎯⎯ Failed Tests 11 ⎯⎯⎯⎯⎯⎯⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-objectRestNoSymbols-rest-ignore-symbols-exec.test.js > exec -AssertionError: expected true to be false // Object.is equality - -- Expected -+ Received - -- false -+ true - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-objectRestNoSymbols-rest-ignore-symbols-exec.test.js:12:19 - 10| expect(a).toBe(1); - 11| expect(r.b).toBe(2); - 12| expect(sym in r).toBe(false); - | ^ - 13| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-rest-remove-unused-excluded-keys-exec.test.js > exec -AssertionError: expected true to be false // Object.is equality - -- Expected -+ Received - -- false -+ true - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-rest-remove-unused-excluded-keys-exec.test.js:10:17 - 8| let { foo,...rest } = obj; - 9| expect("foo" in rest).toBe(false); - 10| expect(called).toBe(false); - | ^ - 11| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js > exec -AssertionError: expected { foo: +0, middle: 1, bar: 1 } to deeply equal { foo: +0, middle: +0, bar: 1 } - -- Expected -+ Received - - Object { - "bar": 1, - "foo": 0, -- "middle": 0, -+ "middle": 1, - } - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-pureGetters-spread-single-call-exec.test.js:13:14 - 11| } }; - 12| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… - 13| expect(res).toEqual({ - | ^ - 14| foo: 0, - 15| middle: 0, - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js > exec -AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-no-object-assign-exec-exec.test.js:14:5 - 12| expect(() => { - 13| const objSpread = _objectSpread({}, obj); - 14| }).toThrow(); - | ^ - 15| const obj2 = { "NOWRITE": 456 }; - 16| expect(() => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js > exec -AssertionError: expected [Function] to throw an error - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-assumption-setSpreadProperties-with-useBuiltIns-no-object-assign-exec-exec.test.js:14:5 - 12| expect(() => { - 13| const objSpread = _objectSpread({}, obj); - 14| }).toThrow(); - | ^ - 15| const obj2 = { "NOWRITE": 456 }; - 16| expect(() => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js > exec -AssertionError: expected [ 1, 2 ] to deeply equal [ 1 ] - -- Expected -+ Received - - Array [ - 1, -+ 2, - ] - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-expression-exec.test.js:11:14 - 9| log.push(2); - 10| } }); - 11| expect(log).toEqual([1]); - | ^ - 12| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-builtins-side-effect-exec.test.js > exec -AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } - -- Expected -+ Received - - Object { -- "a": 2, -+ "a": 1, - "b": 1, - } - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-builtins-side-effect-exec.test.js:9:12 - 7| }; - 8| var o = Object.assign(Object.assign({ a: 3 }, k), { b: k.a++ }); - 9| expect(o).toEqual({ - | ^ - 10| a: 2, - 11| b: 1 - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[8/12]⎯ - - FAIL fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-side-effect-exec.test.js > exec -AssertionError: expected { a: 1, b: 1 } to deeply equal { a: 2, b: 1 } - -- Expected -+ Received - - Object { -- "a": 2, -+ "a": 1, - "b": 1, - } - - ❯ fixtures/babel-plugin-transform-object-rest-spread-test-fixtures-object-spread-loose-side-effect-exec.test.js:9:12 - 7| }; - 8| var o = Object.assign(Object.assign({ a: 3 }, k), { b: k.a++ }); - 9| expect(o).toEqual({ - | ^ - 10| a: 2, - 11| b: 1 - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[9/12]⎯ +⎯⎯⎯⎯⎯⎯⎯ Failed Tests 3 ⎯⎯⎯⎯⎯⎯⎯ FAIL fixtures/babel-preset-env-test-fixtures-plugins-integration-issue-15170-exec.test.js > exec AssertionError: expected [Function] to not throw an error but 'ReferenceError: x is not defined' was thrown @@ -178,7 +31,7 @@ undefined | ^ 7| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[10/12]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[2/4]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js > exec TypeError: Assignment to constant variable. @@ -189,7 +42,7 @@ TypeError: Assignment to constant variable. | ^ 6| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[11/12]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[3/4]⎯ FAIL fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js > exec AssertionError: expected false to be true // Object.is equality @@ -208,5 +61,5 @@ AssertionError: expected false to be true // Object.is equality 11| expect(/hello.world/su.test(input)).toBe(true); 12| }) -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/12]⎯ +⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/4]⎯ diff --git a/tasks/transform_conformance/src/constants.rs b/tasks/transform_conformance/src/constants.rs index d88637b422ad95..49416e76b10deb 100644 --- a/tasks/transform_conformance/src/constants.rs +++ b/tasks/transform_conformance/src/constants.rs @@ -24,7 +24,7 @@ pub const PLUGINS: &[&str] = &[ // "babel-plugin-transform-json-strings", // // ES2018 "babel-plugin-transform-async-generator-functions", - "babel-plugin-transform-object-rest-spread", + // "babel-plugin-transform-object-rest-spread", // // [Regex] "babel-plugin-transform-unicode-property-regex", // "babel-plugin-transform-dotall-regex", // // [Regex] "babel-plugin-transform-named-capturing-groups-regex", diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 8307faf9ae9c31..00c4560e50cd57 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -18,7 +18,7 @@ use oxc_tasks_common::{normalize_path, print_diff_in_terminal, project_root}; use crate::{ constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS, SNAPSHOT_TESTS}, driver::Driver, - fixture_root, oxc_test_root, packages_root, + fixture_root, oxc_test_root, packages_root, snap_root, }; #[derive(Debug)] @@ -194,7 +194,7 @@ impl TestCase { match self.kind { TestCaseKind::Conformance => self.test_conformance(filtered), TestCaseKind::Exec => self.test_exec(filtered), - TestCaseKind::Snapshot => {} + TestCaseKind::Snapshot => self.test_snapshot(filtered), } } @@ -342,7 +342,6 @@ impl TestCase { .unwrap(); let new_file_name: String = normalize_path(unprefixed_path).split('/').collect::>().join("-"); - let mut target_path = fixture_root().join(new_file_name); target_path.set_extension("test.js"); let content = Self::template(content); @@ -373,6 +372,24 @@ test("exec", () => {{ }})"# ) } + + fn test_snapshot(&self, filtered: bool) { + let result = match self.transform(HelperLoaderMode::Runtime) { + Ok(code) => code, + Err(error) => error, + }; + let path = snap_root().join(self.path.strip_prefix(packages_root()).unwrap()); + if filtered { + println!("Input path: {:?}", &self.path); + println!("Output path: {path:?}"); + println!("Input:\n{}\n", fs::read_to_string(&self.path).unwrap()); + println!("Output:\n{result}\n"); + } + if fs::write(&path, &result).is_err() { + fs::create_dir_all(path.parent().unwrap()).unwrap(); + fs::write(path, &result).unwrap(); + } + } } fn get_babel_error(error: &str) -> String { From 514878d927460f637393cbd39d6b6979b774c5ba Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:13:11 +0000 Subject: [PATCH 047/121] fix(transform_conformance): only run exec tests when specified (#7359) --- tasks/transform_conformance/src/lib.rs | 8 ++++---- tasks/transform_conformance/src/test_case.rs | 11 ++++++++--- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/tasks/transform_conformance/src/lib.rs b/tasks/transform_conformance/src/lib.rs index 0453232095c9b1..bba0616aa90622 100644 --- a/tasks/transform_conformance/src/lib.rs +++ b/tasks/transform_conformance/src/lib.rs @@ -80,7 +80,7 @@ impl TestRunner { let _ = fs::remove_dir_all(&fixture_root); let _ = fs::create_dir(&fixture_root); } - let transform_paths = Self::generate_test_cases(root, self.options.filter.as_ref()); + let transform_paths = Self::generate_test_cases(root, &self.options); self.generate_snapshot(root, &snap_root().join(snapshot), transform_paths); if self.options.exec { self.run_vitest(&snap_root().join(exec_snapshot)); @@ -90,7 +90,7 @@ impl TestRunner { fn generate_test_cases( root: &Path, - filter: Option<&String>, + options: &TestRunnerOptions, ) -> IndexMap> { let cwd = root.parent().unwrap_or(root); // use `IndexMap` to keep the order of the test cases the same in insert order. @@ -103,7 +103,7 @@ impl TestRunner { .into_iter() .filter_map(Result::ok) .filter(|e| { - if let Some(filter) = filter { + if let Some(filter) = &options.filter { if !e.path().to_string_lossy().contains(filter) { return false; } @@ -113,7 +113,7 @@ impl TestRunner { .filter_map(|e| TestCase::new(cwd, e.path())) .filter(|test_case| !test_case.skip_test_case()) .map(|mut case| { - case.test(filter.is_some()); + case.test(options); case }) .collect::>(); diff --git a/tasks/transform_conformance/src/test_case.rs b/tasks/transform_conformance/src/test_case.rs index 00c4560e50cd57..bac60cc023ebcc 100644 --- a/tasks/transform_conformance/src/test_case.rs +++ b/tasks/transform_conformance/src/test_case.rs @@ -18,7 +18,7 @@ use oxc_tasks_common::{normalize_path, print_diff_in_terminal, project_root}; use crate::{ constants::{PLUGINS_NOT_SUPPORTED_YET, SKIP_TESTS, SNAPSHOT_TESTS}, driver::Driver, - fixture_root, oxc_test_root, packages_root, snap_root, + fixture_root, oxc_test_root, packages_root, snap_root, TestRunnerOptions, }; #[derive(Debug)] @@ -190,10 +190,15 @@ impl TestCase { Ok(driver.printed()) } - pub fn test(&mut self, filtered: bool) { + pub fn test(&mut self, options: &TestRunnerOptions) { + let filtered = options.filter.is_some(); match self.kind { TestCaseKind::Conformance => self.test_conformance(filtered), - TestCaseKind::Exec => self.test_exec(filtered), + TestCaseKind::Exec => { + if options.exec { + self.test_exec(filtered); + } + } TestCaseKind::Snapshot => self.test_snapshot(filtered), } } From c587dd3cd6c70a4b56a0e8f1362d59540655c2e7 Mon Sep 17 00:00:00 2001 From: Dunqing <29533304+Dunqing@users.noreply.github.com> Date: Tue, 19 Nov 2024 14:29:18 +0000 Subject: [PATCH 048/121] fix(codegen): do not print parenthesis for `in` expression in ArrowFunctionExpression (#7360) Please check out [esbuild](https://esbuild.github.io/try/#dAAwLjI0LjAAACgpID0+ICIiIGluIHt9) --- crates/oxc_codegen/src/gen.rs | 2 +- crates/oxc_codegen/tests/integration/unit.rs | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index a7f1cc4d9b8d72..cbb5409f6988e2 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -1623,7 +1623,7 @@ impl<'a> GenExpr for ArrowFunctionExpression<'a> { if self.expression { if let Some(Statement::ExpressionStatement(stmt)) = &self.body.statements.first() { p.start_of_arrow_expr = p.code_len(); - stmt.expression.print_expr(p, Precedence::Comma, ctx.and_forbid_in(true)); + stmt.expression.print_expr(p, Precedence::Comma, ctx); } } else { self.body.print(p, ctx); diff --git a/crates/oxc_codegen/tests/integration/unit.rs b/crates/oxc_codegen/tests/integration/unit.rs index cbd077a4e25499..17cf30bbea8aab 100644 --- a/crates/oxc_codegen/tests/integration/unit.rs +++ b/crates/oxc_codegen/tests/integration/unit.rs @@ -294,3 +294,10 @@ fn in_expr_in_sequence_in_for_loop_init() { "for ((\"hidden\" in a) && (m = a.hidden), r = 0; s > r; r++) {}\n", ); } + +#[test] +fn in_expr_in_arrow_function_expression() { + test("() => ('foo' in bar)", "() => \"foo\" in bar;\n"); + test("() => 'foo' in bar", "() => \"foo\" in bar;\n"); + test("() => { ('foo' in bar) }", "() => {\n\t\"foo\" in bar;\n};\n"); +} From 234c7b9fef346df773cb2382985330c1d37b786e Mon Sep 17 00:00:00 2001 From: overlookmotel <557937+overlookmotel@users.noreply.github.com> Date: Wed, 20 Nov 2024 03:58:48 +0000 Subject: [PATCH 049/121] feat(traverse): implement `GatherNodeParts` for member expression types (#7363) `GatherNodeParts` was missing support for these types as entry points for collection. --- .../src/ast_operations/gather_node_parts.rs | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs index 3c0d730561f813..47cb7a0b77afa6 100644 --- a/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs +++ b/crates/oxc_traverse/src/ast_operations/gather_node_parts.rs @@ -218,21 +218,39 @@ impl<'a> GatherNodeParts<'a> for MemberExpression<'a> { fn gather(&self, f: &mut F) { match self { MemberExpression::ComputedMemberExpression(expr) => { - expr.object.gather(f); - expr.expression.gather(f); + expr.gather(f); } MemberExpression::StaticMemberExpression(expr) => { - expr.object.gather(f); - expr.property.gather(f); + expr.gather(f); } MemberExpression::PrivateFieldExpression(expr) => { - expr.object.gather(f); - expr.field.gather(f); + expr.gather(f); } } } } +impl<'a> GatherNodeParts<'a> for ComputedMemberExpression<'a> { + fn gather(&self, f: &mut F) { + self.object.gather(f); + self.expression.gather(f); + } +} + +impl<'a> GatherNodeParts<'a> for StaticMemberExpression<'a> { + fn gather(&self, f: &mut F) { + self.object.gather(f); + self.property.gather(f); + } +} + +impl<'a> GatherNodeParts<'a> for PrivateFieldExpression<'a> { + fn gather(&self, f: &mut F) { + self.object.gather(f); + self.field.gather(f); + } +} + impl<'a> GatherNodeParts<'a> for CallExpression<'a> { fn gather(&self, f: &mut F) { self.callee.gather(f); From d3a0119a4203fcd790aeabc4f5fe85fa73db60d8 Mon Sep 17 00:00:00 2001 From: "Alexander S." Date: Wed, 20 Nov 2024 05:44:50 +0100 Subject: [PATCH 050/121] feat(oxlint): add `cwd` property to `LintRunner` (#7352) allows to use multiple `LintRunner` in one file targeting multiple directory. The current problem is for the test in #7348 we can not change `env::current_dir`, so as a workaround I introduce a new property :) See more info here: https://discord.com/channels/1079625926024900739/1117322804291964931/1308179827576016897 --- apps/oxlint/src/lint.rs | 62 +++++++++++++++---- tasks/website/src/linter/snapshots/cli.snap | 1 + .../src/linter/snapshots/cli_terminal.snap | 1 + 3 files changed, 51 insertions(+), 13 deletions(-) diff --git a/apps/oxlint/src/lint.rs b/apps/oxlint/src/lint.rs index 52049828c588b7..e9524802a8f082 100644 --- a/apps/oxlint/src/lint.rs +++ b/apps/oxlint/src/lint.rs @@ -1,4 +1,4 @@ -use std::{env, io::BufWriter, time::Instant}; +use std::{env, io::BufWriter, path::PathBuf, time::Instant}; use ignore::gitignore::Gitignore; use oxc_diagnostics::{DiagnosticService, GraphicalReportHandler}; @@ -18,13 +18,14 @@ use crate::{ pub struct LintRunner { options: LintCommand, + cwd: PathBuf, } impl Runner for LintRunner { type Options = LintCommand; fn new(options: Self::Options) -> Self { - Self { options } + Self { options, cwd: env::current_dir().expect("Failed to get current working directory") } } fn run(self) -> CliRunResult { @@ -51,6 +52,16 @@ impl Runner for LintRunner { let provided_path_count = paths.len(); let now = Instant::now(); + // append cwd to all paths + paths = paths + .into_iter() + .map(|x| { + let mut path_with_cwd = self.cwd.clone(); + path_with_cwd.push(x); + path_with_cwd + }) + .collect(); + // The ignore crate whitelists explicit paths, but priority // should be given to the ignore file. Many users lint // automatically and pass a list of changed files explicitly. @@ -72,13 +83,7 @@ impl Runner for LintRunner { }); } - if let Ok(cwd) = env::current_dir() { - paths.push(cwd); - } else { - return CliRunResult::InvalidOptions { - message: "Failed to get current working directory.".to_string(), - }; - } + paths.push(self.cwd.clone()); } let filter = match Self::get_filters(filter) { @@ -97,8 +102,6 @@ impl Runner for LintRunner { let number_of_files = paths.len(); - let cwd = std::env::current_dir().unwrap(); - let mut oxlintrc = if let Some(config_path) = basic_options.config.as_ref() { match Oxlintrc::from_file(config_path) { Ok(config) => config, @@ -129,8 +132,9 @@ impl Runner for LintRunner { }; } - let mut options = - LintServiceOptions::new(cwd, paths).with_cross_module(builder.plugins().has_import()); + let mut options = LintServiceOptions::new(self.cwd, paths) + .with_cross_module(builder.plugins().has_import()); + let linter = builder.build(); let tsconfig = basic_options.tsconfig; @@ -175,6 +179,12 @@ impl Runner for LintRunner { } impl LintRunner { + #[must_use] + pub fn with_cwd(mut self, cwd: PathBuf) -> Self { + self.cwd = cwd; + self + } + fn get_diagnostic_service( warning_options: &WarningOptions, output_options: &OutputOptions, @@ -235,6 +245,8 @@ impl LintRunner { #[cfg(all(test, not(target_os = "windows")))] mod test { + use std::env; + use super::LintRunner; use crate::cli::{lint_command, CliRunResult, LintResult, Runner}; @@ -248,6 +260,20 @@ mod test { } } + fn test_with_cwd(cwd: &str, args: &[&str]) -> LintResult { + let mut new_args = vec!["--silent"]; + new_args.extend(args); + let options = lint_command().run_inner(new_args.as_slice()).unwrap(); + + let mut current_cwd = env::current_dir().unwrap(); + current_cwd.push(cwd); + + match LintRunner::new(options).with_cwd(current_cwd).run() { + CliRunResult::LintResult(lint_result) => lint_result, + other => panic!("{other:?}"), + } + } + fn test_invalid_options(args: &[&str]) -> String { let mut new_args = vec!["--quiet"]; new_args.extend(args); @@ -279,6 +305,16 @@ mod test { assert_eq!(result.number_of_errors, 0); } + #[test] + fn cwd() { + let args = &["debugger.js"]; + let result = test_with_cwd("fixtures/linter", args); + assert!(result.number_of_rules > 0); + assert_eq!(result.number_of_files, 1); + assert_eq!(result.number_of_warnings, 1); + assert_eq!(result.number_of_errors, 0); + } + #[test] fn file() { let args = &["fixtures/linter/debugger.js"]; diff --git a/tasks/website/src/linter/snapshots/cli.snap b/tasks/website/src/linter/snapshots/cli.snap index 3bddf2116085da..d4184ce620767d 100644 --- a/tasks/website/src/linter/snapshots/cli.snap +++ b/tasks/website/src/linter/snapshots/cli.snap @@ -1,6 +1,7 @@ --- source: tasks/website/src/linter/cli.rs expression: snapshot +snapshot_kind: text --- ## Usage **`oxlint`** \[**`-c`**=_`<./oxlintrc.json>`_\] \[_`PATH`_\]... diff --git a/tasks/website/src/linter/snapshots/cli_terminal.snap b/tasks/website/src/linter/snapshots/cli_terminal.snap index b490bd1f009aa5..3d55cd84e08352 100644 --- a/tasks/website/src/linter/snapshots/cli_terminal.snap +++ b/tasks/website/src/linter/snapshots/cli_terminal.snap @@ -1,6 +1,7 @@ --- source: tasks/website/src/linter/cli.rs expression: snapshot +snapshot_kind: text --- Usage: [-c=<./oxlintrc.json>] [PATH]... From 5190b7fb280dcd15c6de81717c073b06a161ced6 Mon Sep 17 00:00:00 2001 From: "Alexander S." Date: Wed, 20 Nov 2024 05:46:01 +0100 Subject: [PATCH 051/121] test(editor): add test setup (#7361) Tried it with `vitest`, but there was too many problems with `vscode` integration. That why I followed the official guide: - https://code.visualstudio.com/api/working-with-extensions/testing-extension#migrating-from-vscode - https://code.visualstudio.com/api/working-with-extensions/continuous-integration --- .github/workflows/ci_vscode.yml | 11 + .gitignore | 1 + editors/vscode/.vscode-test.mjs | 5 + editors/vscode/client/config.spec.ts | 12 + editors/vscode/package.json | 6 +- pnpm-lock.yaml | 925 +++++++++++++++++++++++++-- 6 files changed, 899 insertions(+), 61 deletions(-) create mode 100644 editors/vscode/.vscode-test.mjs create mode 100644 editors/vscode/client/config.spec.ts diff --git a/.github/workflows/ci_vscode.yml b/.github/workflows/ci_vscode.yml index d2fb3fa86c76a9..0272b7e46a43cf 100644 --- a/.github/workflows/ci_vscode.yml +++ b/.github/workflows/ci_vscode.yml @@ -45,3 +45,14 @@ jobs: - name: Lint VSCode working-directory: editors/vscode run: pnpm run lint + + test: + name: Test + runs-on: ubuntu-latest + steps: + - uses: taiki-e/checkout-action@v1 + - uses: ./.github/actions/pnpm + + - name: Test VSCode + working-directory: editors/vscode + run: xvfb-run -a pnpm run test diff --git a/.gitignore b/.gitignore index dfc41dfbf6d0c7..770ac8bcd3af16 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ target/ /tasks/compat_data/node_modules/ # vscode +/editors/vscode/.vscode-test/ /editors/vscode/node_modules/ /editors/vscode/icon.png /editors/vscode/out/ diff --git a/editors/vscode/.vscode-test.mjs b/editors/vscode/.vscode-test.mjs new file mode 100644 index 00000000000000..40edc76efcfb6e --- /dev/null +++ b/editors/vscode/.vscode-test.mjs @@ -0,0 +1,5 @@ +import { defineConfig } from '@vscode/test-cli'; + +export default defineConfig({ + files: 'out/**/*.spec.js', +}); diff --git a/editors/vscode/client/config.spec.ts b/editors/vscode/client/config.spec.ts new file mode 100644 index 00000000000000..5b71a5f6537c38 --- /dev/null +++ b/editors/vscode/client/config.spec.ts @@ -0,0 +1,12 @@ +import { strictEqual } from 'assert'; +import { ConfigService } from './config.js'; + +suite('default values on initialization', () => { + const service = new ConfigService(); + + strictEqual(service.runTrigger, 'onType'); + strictEqual(service.enable, true); + strictEqual(service.trace, 'off'); + strictEqual(service.configPath, '.eslintrc'); + strictEqual(service.binPath, ''); +}); diff --git a/editors/vscode/package.json b/editors/vscode/package.json index a6078cb3b223fb..cfb54add0232a9 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -136,11 +136,15 @@ "install-extension": "code --install-extension oxc_language_server.vsix --force", "server:build:debug": "cargo build -p oxc_language_server", "server:build:release": "cross-env CARGO_TARGET_DIR=./target cargo build -p oxc_language_server --release", - "lint": "npx oxlint --config=oxlint.json --tsconfig=tsconfig.json" + "lint": "npx oxlint --config=oxlint.json --tsconfig=tsconfig.json", + "test": "esbuild client/config.spec.ts --bundle --outfile=out/config.spec.js --external:vscode --format=cjs --platform=node --target=node16 --minify --sourcemap && vscode-test" }, "devDependencies": { + "@types/mocha": "^10.0.9", "@types/node": "^22.0.0", "@types/vscode": "1.95.0", + "@vscode/test-cli": "^0.0.10", + "@vscode/test-electron": "^2.4.1", "@vscode/vsce": "^3.0.0", "cross-env": "^7.0.3", "esbuild": "^0.24.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d8b33d33269906..e7c77ba9d629cd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,18 +4,6 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false -catalogs: - default: - '@napi-rs/cli': - specifier: 3.0.0-alpha.61 - version: 3.0.0-alpha.61 - typescript: - specifier: 5.6.3 - version: 5.6.3 - vitest: - specifier: 2.1.2 - version: 2.1.2 - importers: .: @@ -36,12 +24,21 @@ importers: specifier: ^9.0.1 version: 9.0.1 devDependencies: + '@types/mocha': + specifier: ^10.0.9 + version: 10.0.9 '@types/node': specifier: ^22.0.0 version: 22.9.0 '@types/vscode': specifier: 1.95.0 version: 1.95.0 + '@vscode/test-cli': + specifier: ^0.0.10 + version: 0.0.10 + '@vscode/test-electron': + specifier: ^2.4.1 + version: 2.4.1 '@vscode/vsce': specifier: ^3.0.0 version: 3.2.1 @@ -169,6 +166,9 @@ packages: resolution: {integrity: sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==} engines: {node: '>=6.9.0'} + '@bcoe/v8-coverage@0.2.3': + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + '@emnapi/core@1.2.0': resolution: {integrity: sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==} @@ -524,9 +524,20 @@ packages: resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} + '@istanbuljs/schema@0.1.3': + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + + '@jridgewell/resolve-uri@3.1.2': + resolution: {integrity: sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==} + engines: {node: '>=6.0.0'} + '@jridgewell/sourcemap-codec@1.5.0': resolution: {integrity: sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==} + '@jridgewell/trace-mapping@0.3.25': + resolution: {integrity: sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==} + '@napi-rs/cli@3.0.0-alpha.61': resolution: {integrity: sha512-xAJJWacaXc2lKMKmchEdnDIVRRnprbzAB5BjM5PXXc9n48tQ32/OqaoCo28u+3pxHD9svymYYYyZIb/e+8PTqg==} engines: {node: '>= 16'} @@ -1015,6 +1026,12 @@ packages: '@types/estree@1.0.6': resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + '@types/istanbul-lib-coverage@2.0.6': + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + + '@types/mocha@10.0.9': + resolution: {integrity: sha512-sicdRoWtYevwxjOHNMPTl3vSfJM6oyW8o1wXeI7uww6b6xHg8eBznQDNSGBCDJmsE8UMxP05JgZRtsKbTqt//Q==} + '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} @@ -1045,6 +1062,9 @@ packages: '@vitest/pretty-format@2.1.2': resolution: {integrity: sha512-FIoglbHrSUlOJPDGIrh2bjX1sNars5HbxlcsFKCtKzu4+5lpsRhOCVcuzp0fEhAGHkPZRIXVNzPcpSlkoZ3LuA==} + '@vitest/pretty-format@2.1.5': + resolution: {integrity: sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==} + '@vitest/runner@2.1.2': resolution: {integrity: sha512-UCsPtvluHO3u7jdoONGjOSil+uON5SSvU9buQh3lP7GgUXHp78guN1wRmZDX4wGK6J10f9NUtP6pO+SFquoMlw==} @@ -1057,6 +1077,15 @@ packages: '@vitest/utils@2.1.2': resolution: {integrity: sha512-zMO2KdYy6mx56btx9JvAqAZ6EyS3g49krMPPrgOp1yxGZiA93HumGk+bZ5jIZtOg5/VBYl5eBmGRQHqq4FG6uQ==} + '@vscode/test-cli@0.0.10': + resolution: {integrity: sha512-B0mMH4ia+MOOtwNiLi79XhA+MLmUItIC8FckEuKrVAVriIuSWjt7vv4+bF8qVFiNFe4QRfzPaIZk39FZGWEwHA==} + engines: {node: '>=18'} + hasBin: true + + '@vscode/test-electron@2.4.1': + resolution: {integrity: sha512-Gc6EdaLANdktQ1t+zozoBVRynfIsMKMc94Svu1QreOBC8y76x4tvaK32TljrLi1LI2+PK58sDVbL7ALdqf3VRQ==} + engines: {node: '>=16'} + '@vscode/vsce-sign-alpine-arm64@2.0.2': resolution: {integrity: sha512-E80YvqhtZCLUv3YAf9+tIbbqoinWLCO/B3j03yQPbjT3ZIHCliKZlsy1peNc4XNZ5uIb87Jn0HWx/ZbPXviuAQ==} cpu: [arm64] @@ -1118,6 +1147,10 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} + ansi-colors@4.1.3: + resolution: {integrity: sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==} + engines: {node: '>=6'} + ansi-escapes@4.3.2: resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} engines: {node: '>=8'} @@ -1142,6 +1175,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1170,9 +1207,16 @@ packages: before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + bl@5.1.0: + resolution: {integrity: sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==} + body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -1186,6 +1230,13 @@ packages: brace-expansion@2.0.1: resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + + browser-stdout@1.3.1: + resolution: {integrity: sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==} + buffer-crc32@0.2.13: resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} @@ -1195,10 +1246,18 @@ packages: buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + bytes@3.1.2: resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} engines: {node: '>= 0.8'} + c8@9.1.0: + resolution: {integrity: sha512-mBWcT5iqNir1zIkzSPyI3NCR9EZCVI3WUD+AVO17MVWTSFNyUueXE82qTeampNtTr+ilN/5Ua3j24LgbCKjDVg==} + engines: {node: '>=14.14.0'} + hasBin: true + cac@6.7.14: resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} engines: {node: '>=8'} @@ -1207,14 +1266,26 @@ packages: resolution: {integrity: sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==} engines: {node: '>= 0.4'} - chai@5.1.1: - resolution: {integrity: sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==} + camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + + chai@5.1.2: + resolution: {integrity: sha512-aGtmf24DW6MLHHG5gCx4zaI3uBq3KRtxeVs0DjFH6Z0rDNbsvTxFASFvdj79pxjxZ8/5u3PIiN3IwEIQkiiuPw==} engines: {node: '>=12'} chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} + chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + + chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + chardet@0.7.0: resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} @@ -1229,6 +1300,10 @@ packages: resolution: {integrity: sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==} engines: {node: '>=18.17'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chownr@1.1.4: resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} @@ -1239,6 +1314,10 @@ packages: ci-info@2.0.0: resolution: {integrity: sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==} + cli-cursor@4.0.0: + resolution: {integrity: sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + cli-spinners@2.9.2: resolution: {integrity: sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==} engines: {node: '>=6'} @@ -1252,6 +1331,13 @@ packages: peerDependencies: typanion: '*' + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + cockatiel@3.2.1: resolution: {integrity: sha512-gfrHV6ZPkquExvMh9IOkKsBzNDk6sDuZ6DdBGUBkvFnTCqCxzpuq48RySgP0AnaqQkw2zynOFj9yly6T1Q2G5Q==} engines: {node: '>=16'} @@ -1291,6 +1377,9 @@ packages: resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} engines: {node: '>= 0.6'} + convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + cookie-signature@1.0.6: resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} @@ -1298,6 +1387,9 @@ packages: resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} engines: {node: '>= 0.6'} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + cross-env@7.0.3: resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} @@ -1331,6 +1423,10 @@ packages: supports-color: optional: true + decamelize@4.0.0: + resolution: {integrity: sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==} + engines: {node: '>=10'} + decompress-response@6.0.0: resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} engines: {node: '>=10'} @@ -1372,6 +1468,10 @@ packages: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} + diff@5.2.0: + resolution: {integrity: sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==} + engines: {node: '>=0.3.1'} + dom-serializer@2.0.0: resolution: {integrity: sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==} @@ -1394,6 +1494,9 @@ packages: ee-first@1.1.1: resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + emoji-regex@10.4.0: + resolution: {integrity: sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -1414,6 +1517,10 @@ packages: end-of-stream@1.4.4: resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.17.1: + resolution: {integrity: sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==} + engines: {node: '>=10.13.0'} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -1436,6 +1543,10 @@ packages: engines: {node: '>=18'} hasBin: true + escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + escape-html@1.0.3: resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} @@ -1443,6 +1554,10 @@ packages: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + estree-walker@3.0.3: resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==} @@ -1469,10 +1584,22 @@ packages: fd-slicer@1.1.0: resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + finalhandler@1.3.1: resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} engines: {node: '>= 0.8'} + find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + + flat@5.0.2: + resolution: {integrity: sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==} + hasBin: true + follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -1501,6 +1628,9 @@ packages: fs-constants@1.0.0: resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -1509,8 +1639,9 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} - get-func-name@2.0.2: - resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} get-intrinsic@1.2.4: resolution: {integrity: sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==} @@ -1519,6 +1650,10 @@ packages: github-from-package@0.0.0: resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + glob@10.4.5: resolution: {integrity: sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==} hasBin: true @@ -1528,13 +1663,29 @@ packages: engines: {node: 20 || >=22} hasBin: true + glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + deprecated: Glob versions prior to v9 are no longer supported + + glob@8.1.0: + resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} + engines: {node: '>=12'} + deprecated: Glob versions prior to v9 are no longer supported + gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + has-flag@3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} engines: {node: '>=4'} + has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + has-property-descriptors@1.0.2: resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} @@ -1550,10 +1701,17 @@ packages: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} + he@1.2.0: + resolution: {integrity: sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==} + hasBin: true + hosted-git-info@4.1.0: resolution: {integrity: sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==} engines: {node: '>=10'} + html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + htmlparser2@9.1.0: resolution: {integrity: sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==} @@ -1580,6 +1738,13 @@ packages: ieee754@1.2.1: resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + immediate@3.0.6: + resolution: {integrity: sha512-XXOFtyqDjNDAQxVfYxuF7g9Il/IbWmmlQg2MYKOH8ExIT1qg6xc4zyS3HaEEATgs1btfzxq15ciUiY7gjSXRGQ==} + + inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + deprecated: This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful. + inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} @@ -1594,6 +1759,10 @@ packages: resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} engines: {node: '>= 0.10'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-ci@2.0.0: resolution: {integrity: sha512-YfJT7rkpQB0updsdHLGWrvhBJfcfzNNawYDNIyQXJz0IViGf75O8EBPKSdvw2rF+LGCsX4FZ8tcr3b19LcZq4w==} hasBin: true @@ -1603,17 +1772,60 @@ packages: engines: {node: '>=8'} hasBin: true + is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + is-fullwidth-code-point@3.0.0: resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} engines: {node: '>=8'} + is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + + is-interactive@2.0.0: + resolution: {integrity: sha512-qP1vozQRI+BMOPcjFzrjXuQvdak2pHNUMZoeG2eRbiSqyvbEf/wQtEOTOX1guk6E3t36RkaqiSt8A/6YElNxLQ==} + engines: {node: '>=12'} + + is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + + is-plain-obj@2.1.0: + resolution: {integrity: sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==} + engines: {node: '>=8'} + + is-unicode-supported@0.1.0: + resolution: {integrity: sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==} + engines: {node: '>=10'} + + is-unicode-supported@1.3.0: + resolution: {integrity: sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==} + engines: {node: '>=12'} + is-wsl@2.2.0: resolution: {integrity: sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==} engines: {node: '>=8'} + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + + istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + + istanbul-reports@3.1.7: + resolution: {integrity: sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==} + engines: {node: '>=8'} + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -1632,6 +1844,9 @@ packages: resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} engines: {node: '>=12', npm: '>=6'} + jszip@3.10.1: + resolution: {integrity: sha512-xXDvecyTpGLrqFrvkrUSoxxfJI5AH7U8zxxtVclpsUtMCq4JQ290LY8AW5c7Ggnr/Y/oK+bQMbqK2qmtk3pN4g==} + jwa@1.4.1: resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} @@ -1651,9 +1866,16 @@ packages: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} engines: {node: '>=6'} + lie@3.3.0: + resolution: {integrity: sha512-UaiMJzeWRlEujzAuw5LokY1L5ecNQYZKfmyZ9L7wDHb/p5etKaxXhohBcrw0EYby+G/NA52vRSN4N39dxHAIwQ==} + linkify-it@5.0.0: resolution: {integrity: sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==} + locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + lodash-es@4.17.21: resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} @@ -1678,8 +1900,16 @@ packages: lodash.once@4.1.1: resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} - loupe@3.1.1: - resolution: {integrity: sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==} + log-symbols@4.1.0: + resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} + engines: {node: '>=10'} + + log-symbols@5.1.0: + resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} + engines: {node: '>=12'} + + loupe@3.1.2: + resolution: {integrity: sha512-23I4pFZHmAemUnz8WZXbYRSKYj801VDaNv9ETuMh7IrMc7VuVVSo+Z9iLE3ni30+U48iDWfi30d3twAXBYmnCg==} lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} @@ -1692,8 +1922,12 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} - magic-string@0.30.11: - resolution: {integrity: sha512-+Wri9p0QHMy+545hKww7YAu5NyzF8iomPL/RQazugQ9+Ez4Ic3mERMd8ZTX5rfK944j+560ZJi8iAwgak1Ac7A==} + magic-string@0.30.13: + resolution: {integrity: sha512-8rYBO+MsWkgjDSOvLomYnzhdwEG51olQ4zL5KXnNJWV5MNmrb4rTZdrtkhxjnD/QyZUqR/Z/XDsUs/4ej2nx0g==} + + make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} markdown-it@14.1.0: resolution: {integrity: sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==} @@ -1726,6 +1960,10 @@ packages: engines: {node: '>=4'} hasBin: true + mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + mimic-response@3.1.0: resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} engines: {node: '>=10'} @@ -1764,6 +2002,11 @@ packages: engines: {node: '>=10'} hasBin: true + mocha@10.8.2: + resolution: {integrity: sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==} + engines: {node: '>= 14.0.0'} + hasBin: true + ms@2.0.0: resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} @@ -1796,6 +2039,10 @@ packages: node-addon-api@4.3.0: resolution: {integrity: sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==} + normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + nth-check@2.1.1: resolution: {integrity: sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==} @@ -1810,10 +2057,18 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + open@8.4.2: resolution: {integrity: sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==} engines: {node: '>=12'} + ora@7.0.1: + resolution: {integrity: sha512-0TUxTiFJWv+JnjWm4o9yvuskpEJLXTcng8MJuKd+SzAzp2o+OP3HWqNhB4OdJRt1Vsd9/mR0oyaEYlOnL7XIRw==} + engines: {node: '>=16'} + os-tmpdir@1.0.2: resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} engines: {node: '>=0.10.0'} @@ -1828,9 +2083,20 @@ packages: engines: {node: '>=14.*'} hasBin: true + p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + + p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + package-json-from-dist@1.0.1: resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + pako@1.0.11: + resolution: {integrity: sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==} + parse-semver@1.1.1: resolution: {integrity: sha512-Eg1OuNntBMH0ojvEKSrvDSnwLmvVuUOSdylH/pSCPNMIspLlweJyIWXCE+k/5hm3cj/EBUYwmWkjhBALNP4LXQ==} @@ -1847,6 +2113,14 @@ packages: resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} engines: {node: '>= 0.8'} + path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + + path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + path-key@3.1.1: resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} engines: {node: '>=8'} @@ -1875,6 +2149,10 @@ packages: picocolors@1.1.0: resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + postcss@8.4.47: resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} engines: {node: ^10 || ^12 || >=14} @@ -1884,6 +2162,9 @@ packages: engines: {node: '>=10'} hasBin: true + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -1902,6 +2183,9 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + range-parser@1.2.1: resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} engines: {node: '>= 0.6'} @@ -1918,13 +2202,28 @@ packages: resolution: {integrity: sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==} engines: {node: '>=0.8'} + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + restore-cursor@4.0.0: + resolution: {integrity: sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + rimraf@5.0.10: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true @@ -1941,6 +2240,9 @@ packages: rxjs@7.8.1: resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -1963,6 +2265,9 @@ packages: resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} engines: {node: '>= 0.8.0'} + serialize-javascript@6.0.2: + resolution: {integrity: sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==} + serve-static@1.16.2: resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} engines: {node: '>= 0.8.0'} @@ -1971,6 +2276,9 @@ packages: resolution: {integrity: sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==} engines: {node: '>= 0.4'} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + setprototypeof@1.2.0: resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} @@ -1989,6 +2297,9 @@ packages: siginfo@2.0.0: resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + signal-exit@4.1.0: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} @@ -2010,8 +2321,12 @@ packages: resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} engines: {node: '>= 0.8'} - std-env@3.7.0: - resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + std-env@3.8.0: + resolution: {integrity: sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==} + + stdin-discarder@0.1.0: + resolution: {integrity: sha512-xhV7w8S+bUwlPTb4bAOUQhv8/cSS5offJuX8GQGq32ONF0ZtDWKfkdomM3HMRA+LhX6um/FZ0COqlwsjD53LeQ==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} stoppable@1.1.0: resolution: {integrity: sha512-KXDYZ9dszj6bzvnEMRYvxgeTHU74QBFL54XKtP3nyMuJ81CFYtABZ3bAzL2EdFUaEwJOBOgENyFj3R7oTzDyyw==} @@ -2025,6 +2340,13 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string-width@6.1.0: + resolution: {integrity: sha512-k01swCJAgQmuADB0YIc+7TuatfNvTBVOoaUWJjTB9R4VJzR5vNWzf5t42ESVZFPS8xTySF7CAdV4t/aaIm3UnQ==} + engines: {node: '>=16'} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2040,10 +2362,30 @@ packages: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} + strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + supports-color@5.5.0: resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} engines: {node: '>=4'} + supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + + supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + + supports-color@9.4.0: + resolution: {integrity: sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==} + engines: {node: '>=12'} + + tapable@2.2.1: + resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} + engines: {node: '>=6'} + tar-fs@2.1.1: resolution: {integrity: sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==} @@ -2055,11 +2397,15 @@ packages: resolution: {integrity: sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==} engines: {node: '>=18'} + test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + tinybench@2.9.0: resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==} - tinyexec@0.3.0: - resolution: {integrity: sha512-tVGE0mVJPGb0chKhqmsoosjsS+qUnJVGJpZgsHYQcGoPlG3B51R3PouqTgEGH2Dc9jjFyOqOpix6ZHNMXp1FZg==} + tinyexec@0.3.1: + resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} tinypool@1.0.1: resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} @@ -2081,6 +2427,10 @@ packages: resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==} engines: {node: '>=14.14'} + to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + toidentifier@1.0.1: resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} engines: {node: '>=0.6'} @@ -2151,6 +2501,10 @@ packages: resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} hasBin: true + v8-to-istanbul@9.3.0: + resolution: {integrity: sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==} + engines: {node: '>=10.12.0'} + vary@1.1.2: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} @@ -2251,6 +2605,9 @@ packages: engines: {node: '>=8'} hasBin: true + workerpool@6.5.1: + resolution: {integrity: sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -2274,6 +2631,10 @@ packages: resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} engines: {node: '>=4.0'} + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + yallist@4.0.0: resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} @@ -2281,6 +2642,26 @@ packages: resolution: {integrity: sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==} engines: {node: '>=18'} + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs-unparser@2.0.0: + resolution: {integrity: sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==} + engines: {node: '>=10'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yauzl@2.10.0: resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} @@ -2291,6 +2672,10 @@ packages: yazl@2.5.1: resolution: {integrity: sha512-phENi2PLiHnHb6QBVot+dJnaAZ0xosj7p3fWl+znIjBDlnMI2PsZCJZ306BPTFOaHf5qdDEI8x5qFrSOBN5vrw==} + yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + yoctocolors-cjs@2.1.2: resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==} engines: {node: '>=18'} @@ -2380,6 +2765,8 @@ snapshots: dependencies: regenerator-runtime: 0.14.1 + '@bcoe/v8-coverage@0.2.3': {} + '@emnapi/core@1.2.0': dependencies: '@emnapi/wasi-threads': 1.0.1 @@ -2647,8 +3034,17 @@ snapshots: dependencies: minipass: 7.1.2 + '@istanbuljs/schema@0.1.3': {} + + '@jridgewell/resolve-uri@3.1.2': {} + '@jridgewell/sourcemap-codec@1.5.0': {} + '@jridgewell/trace-mapping@0.3.25': + dependencies: + '@jridgewell/resolve-uri': 3.1.2 + '@jridgewell/sourcemap-codec': 1.5.0 + '@napi-rs/cli@3.0.0-alpha.61(@emnapi/runtime@1.2.0)': dependencies: '@napi-rs/cross-toolchain': 0.0.16 @@ -2656,7 +3052,7 @@ snapshots: '@octokit/rest': 21.0.2 clipanion: 3.2.1(typanion@3.14.0) colorette: 2.0.20 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) inquirer: 10.2.0 js-yaml: 4.1.0 lodash-es: 4.17.21 @@ -2679,7 +3075,7 @@ snapshots: dependencies: '@napi-rs/lzma': 1.3.1 '@napi-rs/tar': 0.1.4 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -3020,6 +3416,10 @@ snapshots: '@types/estree@1.0.6': {} + '@types/istanbul-lib-coverage@2.0.6': {} + + '@types/mocha@10.0.9': {} + '@types/mute-stream@0.0.4': dependencies: '@types/node': 22.9.0 @@ -3036,14 +3436,14 @@ snapshots: dependencies: '@vitest/spy': 2.1.2 '@vitest/utils': 2.1.2 - chai: 5.1.1 + chai: 5.1.2 tinyrainbow: 1.2.0 '@vitest/mocker@2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.9.0))': dependencies: '@vitest/spy': 2.1.2 estree-walker: 3.0.3 - magic-string: 0.30.11 + magic-string: 0.30.13 optionalDependencies: vite: 5.4.8(@types/node@22.9.0) @@ -3051,6 +3451,10 @@ snapshots: dependencies: tinyrainbow: 1.2.0 + '@vitest/pretty-format@2.1.5': + dependencies: + tinyrainbow: 1.2.0 + '@vitest/runner@2.1.2': dependencies: '@vitest/utils': 2.1.2 @@ -3059,7 +3463,7 @@ snapshots: '@vitest/snapshot@2.1.2': dependencies: '@vitest/pretty-format': 2.1.2 - magic-string: 0.30.11 + magic-string: 0.30.13 pathe: 1.1.2 '@vitest/spy@2.1.2': @@ -3069,9 +3473,31 @@ snapshots: '@vitest/utils@2.1.2': dependencies: '@vitest/pretty-format': 2.1.2 - loupe: 3.1.1 + loupe: 3.1.2 tinyrainbow: 1.2.0 + '@vscode/test-cli@0.0.10': + dependencies: + '@types/mocha': 10.0.9 + c8: 9.1.0 + chokidar: 3.6.0 + enhanced-resolve: 5.17.1 + glob: 10.4.5 + minimatch: 9.0.5 + mocha: 10.8.2 + supports-color: 9.4.0 + yargs: 17.7.2 + + '@vscode/test-electron@2.4.1': + dependencies: + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.5 + jszip: 3.10.1 + ora: 7.0.1 + semver: 7.6.3 + transitivePeerDependencies: + - supports-color + '@vscode/vsce-sign-alpine-arm64@2.0.2': optional: true @@ -3149,10 +3575,12 @@ snapshots: agent-base@7.1.1: dependencies: - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color + ansi-colors@4.1.3: {} + ansi-escapes@4.3.2: dependencies: type-fest: 0.21.3 @@ -3171,6 +3599,11 @@ snapshots: ansi-styles@6.2.1: {} + anymatch@3.1.3: + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + argparse@2.0.1: {} array-flatten@1.1.1: {} @@ -3194,11 +3627,12 @@ snapshots: balanced-match@1.0.2: {} - base64-js@1.5.1: - optional: true + base64-js@1.5.1: {} before-after-hook@3.0.2: {} + binary-extensions@2.3.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -3206,6 +3640,12 @@ snapshots: readable-stream: 3.6.2 optional: true + bl@5.1.0: + dependencies: + buffer: 6.0.3 + inherits: 2.0.4 + readable-stream: 3.6.2 + body-parser@1.20.3: dependencies: bytes: 3.1.2 @@ -3234,6 +3674,12 @@ snapshots: dependencies: balanced-match: 1.0.2 + braces@3.0.3: + dependencies: + fill-range: 7.1.1 + + browser-stdout@1.3.1: {} + buffer-crc32@0.2.13: {} buffer-equal-constant-time@1.0.1: {} @@ -3244,8 +3690,27 @@ snapshots: ieee754: 1.2.1 optional: true + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + bytes@3.1.2: {} + c8@9.1.0: + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@istanbuljs/schema': 0.1.3 + find-up: 5.0.0 + foreground-child: 3.3.0 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-report: 3.0.1 + istanbul-reports: 3.1.7 + test-exclude: 6.0.0 + v8-to-istanbul: 9.3.0 + yargs: 17.7.2 + yargs-parser: 21.1.1 + cac@6.7.14: {} call-bind@1.0.7: @@ -3256,12 +3721,14 @@ snapshots: get-intrinsic: 1.2.4 set-function-length: 1.2.2 - chai@5.1.1: + camelcase@6.3.0: {} + + chai@5.1.2: dependencies: assertion-error: 2.0.1 check-error: 2.1.1 deep-eql: 5.0.2 - loupe: 3.1.1 + loupe: 3.1.2 pathval: 2.0.0 chalk@2.4.2: @@ -3270,6 +3737,13 @@ snapshots: escape-string-regexp: 1.0.5 supports-color: 5.5.0 + chalk@4.1.2: + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + + chalk@5.3.0: {} + chardet@0.7.0: {} check-error@2.1.1: {} @@ -3297,6 +3771,18 @@ snapshots: undici: 6.20.1 whatwg-mimetype: 4.0.0 + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chownr@1.1.4: optional: true @@ -3304,6 +3790,10 @@ snapshots: ci-info@2.0.0: {} + cli-cursor@4.0.0: + dependencies: + restore-cursor: 4.0.0 + cli-spinners@2.9.2: {} cli-width@4.1.0: {} @@ -3312,6 +3802,18 @@ snapshots: dependencies: typanion: 3.14.0 + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + cockatiel@3.2.1: {} color-convert@1.9.3: @@ -3342,10 +3844,14 @@ snapshots: content-type@1.0.5: {} + convert-source-map@2.0.0: {} + cookie-signature@1.0.6: {} cookie@0.7.1: {} + core-util-is@1.0.3: {} + cross-env@7.0.3: dependencies: cross-spawn: 7.0.3 @@ -3370,9 +3876,13 @@ snapshots: dependencies: ms: 2.0.0 - debug@4.3.7: + debug@4.3.7(supports-color@8.1.1): dependencies: ms: 2.1.3 + optionalDependencies: + supports-color: 8.1.1 + + decamelize@4.0.0: {} decompress-response@6.0.0: dependencies: @@ -3403,6 +3913,8 @@ snapshots: detect-libc@2.0.3: optional: true + diff@5.2.0: {} + dom-serializer@2.0.0: dependencies: domelementtype: 2.3.0 @@ -3429,6 +3941,8 @@ snapshots: ee-first@1.1.1: {} + emoji-regex@10.4.0: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -3447,6 +3961,11 @@ snapshots: once: 1.4.0 optional: true + enhanced-resolve@5.17.1: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.2.1 + entities@4.5.0: {} es-define-property@1.0.0: @@ -3508,10 +4027,14 @@ snapshots: '@esbuild/win32-ia32': 0.24.0 '@esbuild/win32-x64': 0.24.0 + escalade@3.2.0: {} + escape-html@1.0.3: {} escape-string-regexp@1.0.5: {} + escape-string-regexp@4.0.0: {} + estree-walker@3.0.3: dependencies: '@types/estree': 1.0.6 @@ -3569,6 +4092,10 @@ snapshots: dependencies: pend: 1.2.0 + fill-range@7.1.1: + dependencies: + to-regex-range: 5.0.1 + finalhandler@1.3.1: dependencies: debug: 2.6.9 @@ -3581,6 +4108,13 @@ snapshots: transitivePeerDependencies: - supports-color + find-up@5.0.0: + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + + flat@5.0.2: {} + follow-redirects@1.15.9: {} foreground-child@3.3.0: @@ -3601,12 +4135,14 @@ snapshots: fs-constants@1.0.0: optional: true + fs.realpath@1.0.0: {} + fsevents@2.3.3: optional: true function-bind@1.1.2: {} - get-func-name@2.0.2: {} + get-caller-file@2.0.5: {} get-intrinsic@1.2.4: dependencies: @@ -3619,6 +4155,10 @@ snapshots: github-from-package@0.0.0: optional: true + glob-parent@5.1.2: + dependencies: + is-glob: 4.0.3 + glob@10.4.5: dependencies: foreground-child: 3.3.0 @@ -3637,12 +4177,33 @@ snapshots: package-json-from-dist: 1.0.1 path-scurry: 2.0.0 + glob@7.2.3: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + + glob@8.1.0: + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 5.1.6 + once: 1.4.0 + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 + graceful-fs@4.2.11: {} + has-flag@3.0.0: {} + has-flag@4.0.0: {} + has-property-descriptors@1.0.2: dependencies: es-define-property: 1.0.0 @@ -3655,10 +4216,14 @@ snapshots: dependencies: function-bind: 1.1.2 + he@1.2.0: {} + hosted-git-info@4.1.0: dependencies: lru-cache: 6.0.0 + html-escaper@2.0.2: {} + htmlparser2@9.1.0: dependencies: domelementtype: 2.3.0 @@ -3677,14 +4242,14 @@ snapshots: http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.1 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color https-proxy-agent@7.0.5: dependencies: agent-base: 7.1.1 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -3696,8 +4261,14 @@ snapshots: dependencies: safer-buffer: 2.1.2 - ieee754@1.2.1: - optional: true + ieee754@1.2.1: {} + + immediate@3.0.6: {} + + inflight@1.0.6: + dependencies: + once: 1.4.0 + wrappy: 1.0.2 inherits@2.0.4: {} @@ -3716,20 +4287,55 @@ snapshots: ipaddr.js@1.9.1: {} + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-ci@2.0.0: dependencies: ci-info: 2.0.0 is-docker@2.2.1: {} + is-extglob@2.1.1: {} + is-fullwidth-code-point@3.0.0: {} + is-glob@4.0.3: + dependencies: + is-extglob: 2.1.1 + + is-interactive@2.0.0: {} + + is-number@7.0.0: {} + + is-plain-obj@2.1.0: {} + + is-unicode-supported@0.1.0: {} + + is-unicode-supported@1.3.0: {} + is-wsl@2.2.0: dependencies: is-docker: 2.2.1 + isarray@1.0.0: {} + isexe@2.0.0: {} + istanbul-lib-coverage@3.2.2: {} + + istanbul-lib-report@3.0.1: + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + + istanbul-reports@3.1.7: + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -3759,6 +4365,13 @@ snapshots: ms: 2.1.3 semver: 7.6.3 + jszip@3.10.1: + dependencies: + lie: 3.3.0 + pako: 1.0.11 + readable-stream: 2.3.8 + setimmediate: 1.0.5 + jwa@1.4.1: dependencies: buffer-equal-constant-time: 1.0.1 @@ -3789,10 +4402,18 @@ snapshots: leven@3.1.0: {} + lie@3.3.0: + dependencies: + immediate: 3.0.6 + linkify-it@5.0.0: dependencies: uc.micro: 2.1.0 + locate-path@6.0.0: + dependencies: + p-locate: 5.0.0 + lodash-es@4.17.21: {} lodash.includes@4.3.0: {} @@ -3809,9 +4430,17 @@ snapshots: lodash.once@4.1.1: {} - loupe@3.1.1: + log-symbols@4.1.0: dependencies: - get-func-name: 2.0.2 + chalk: 4.1.2 + is-unicode-supported: 0.1.0 + + log-symbols@5.1.0: + dependencies: + chalk: 5.3.0 + is-unicode-supported: 1.3.0 + + loupe@3.1.2: {} lru-cache@10.4.3: {} @@ -3821,10 +4450,14 @@ snapshots: dependencies: yallist: 4.0.0 - magic-string@0.30.11: + magic-string@0.30.13: dependencies: '@jridgewell/sourcemap-codec': 1.5.0 + make-dir@4.0.0: + dependencies: + semver: 7.6.3 + markdown-it@14.1.0: dependencies: argparse: 2.0.1 @@ -3850,6 +4483,8 @@ snapshots: mime@1.6.0: {} + mimic-fn@2.1.0: {} + mimic-response@3.1.0: optional: true @@ -3884,6 +4519,29 @@ snapshots: mkdirp@3.0.1: {} + mocha@10.8.2: + dependencies: + ansi-colors: 4.1.3 + browser-stdout: 1.3.1 + chokidar: 3.6.0 + debug: 4.3.7(supports-color@8.1.1) + diff: 5.2.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 8.1.0 + he: 1.2.0 + js-yaml: 4.1.0 + log-symbols: 4.1.0 + minimatch: 5.1.6 + ms: 2.1.3 + serialize-javascript: 6.0.2 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 6.5.1 + yargs: 16.2.0 + yargs-parser: 20.2.9 + yargs-unparser: 2.0.0 + ms@2.0.0: {} ms@2.1.3: {} @@ -3907,6 +4565,8 @@ snapshots: node-addon-api@4.3.0: optional: true + normalize-path@3.0.0: {} + nth-check@2.1.1: dependencies: boolbase: 1.0.0 @@ -3920,7 +4580,10 @@ snapshots: once@1.4.0: dependencies: wrappy: 1.0.2 - optional: true + + onetime@5.1.2: + dependencies: + mimic-fn: 2.1.0 open@8.4.2: dependencies: @@ -3928,6 +4591,18 @@ snapshots: is-docker: 2.2.1 is-wsl: 2.2.0 + ora@7.0.1: + dependencies: + chalk: 5.3.0 + cli-cursor: 4.0.0 + cli-spinners: 2.9.2 + is-interactive: 2.0.0 + is-unicode-supported: 1.3.0 + log-symbols: 5.1.0 + stdin-discarder: 0.1.0 + string-width: 6.1.0 + strip-ansi: 7.1.0 + os-tmpdir@1.0.2: {} ovsx@0.10.0: @@ -3955,8 +4630,18 @@ snapshots: '@oxlint/win32-arm64': 0.11.1 '@oxlint/win32-x64': 0.11.1 + p-limit@3.1.0: + dependencies: + yocto-queue: 0.1.0 + + p-locate@5.0.0: + dependencies: + p-limit: 3.1.0 + package-json-from-dist@1.0.1: {} + pako@1.0.11: {} + parse-semver@1.1.1: dependencies: semver: 5.7.2 @@ -3976,6 +4661,10 @@ snapshots: parseurl@1.3.3: {} + path-exists@4.0.0: {} + + path-is-absolute@1.0.1: {} + path-key@3.1.1: {} path-scurry@1.11.1: @@ -3998,6 +4687,8 @@ snapshots: picocolors@1.1.0: {} + picomatch@2.3.1: {} + postcss@8.4.47: dependencies: nanoid: 3.3.7 @@ -4020,6 +4711,8 @@ snapshots: tunnel-agent: 0.6.0 optional: true + process-nextick-args@2.0.1: {} + proxy-addr@2.0.7: dependencies: forwarded: 0.2.0 @@ -4039,6 +4732,10 @@ snapshots: dependencies: side-channel: 1.0.6 + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + range-parser@1.2.1: {} raw-body@2.5.2: @@ -4060,15 +4757,35 @@ snapshots: dependencies: mute-stream: 0.0.8 + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 string_decoder: 1.3.0 util-deprecate: 1.0.2 - optional: true + + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 regenerator-runtime@0.14.1: {} + require-directory@2.1.1: {} + + restore-cursor@4.0.0: + dependencies: + onetime: 5.1.2 + signal-exit: 3.0.7 + rimraf@5.0.10: dependencies: glob: 10.4.5 @@ -4101,6 +4818,8 @@ snapshots: dependencies: tslib: 2.8.0 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {} @@ -4129,6 +4848,10 @@ snapshots: transitivePeerDependencies: - supports-color + serialize-javascript@6.0.2: + dependencies: + randombytes: 2.1.0 + serve-static@1.16.2: dependencies: encodeurl: 2.0.0 @@ -4147,6 +4870,8 @@ snapshots: gopd: 1.0.1 has-property-descriptors: 1.0.2 + setimmediate@1.0.5: {} + setprototypeof@1.2.0: {} shebang-command@2.0.0: @@ -4164,6 +4889,8 @@ snapshots: siginfo@2.0.0: {} + signal-exit@3.0.7: {} + signal-exit@4.1.0: {} simple-concat@1.0.1: @@ -4182,7 +4909,11 @@ snapshots: statuses@2.0.1: {} - std-env@3.7.0: {} + std-env@3.8.0: {} + + stdin-discarder@0.1.0: + dependencies: + bl: 5.1.0 stoppable@1.1.0: {} @@ -4198,10 +4929,19 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string-width@6.1.0: + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 10.4.0 + strip-ansi: 7.1.0 + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 - optional: true strip-ansi@6.0.1: dependencies: @@ -4214,10 +4954,24 @@ snapshots: strip-json-comments@2.0.1: optional: true + strip-json-comments@3.1.1: {} + supports-color@5.5.0: dependencies: has-flag: 3.0.0 + supports-color@7.2.0: + dependencies: + has-flag: 4.0.0 + + supports-color@8.1.1: + dependencies: + has-flag: 4.0.0 + + supports-color@9.4.0: {} + + tapable@2.2.1: {} + tar-fs@2.1.1: dependencies: chownr: 1.1.4 @@ -4244,9 +4998,15 @@ snapshots: mkdirp: 3.0.1 yallist: 5.0.0 + test-exclude@6.0.0: + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + tinybench@2.9.0: {} - tinyexec@0.3.0: {} + tinyexec@0.3.1: {} tinypool@1.0.1: {} @@ -4260,6 +5020,10 @@ snapshots: tmp@0.2.3: {} + to-regex-range@5.0.1: + dependencies: + is-number: 7.0.0 + toidentifier@1.0.1: {} toml@3.0.0: {} @@ -4304,19 +5068,24 @@ snapshots: url-join@4.0.1: {} - util-deprecate@1.0.2: - optional: true + util-deprecate@1.0.2: {} utils-merge@1.0.1: {} uuid@8.3.2: {} + v8-to-istanbul@9.3.0: + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + vary@1.1.2: {} vite-node@2.1.2(@types/node@22.9.0): dependencies: cac: 6.7.14 - debug: 4.3.7 + debug: 4.3.7(supports-color@8.1.1) pathe: 1.1.2 vite: 5.4.8(@types/node@22.9.0) transitivePeerDependencies: @@ -4343,18 +5112,18 @@ snapshots: dependencies: '@vitest/expect': 2.1.2 '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.9.0)) - '@vitest/pretty-format': 2.1.2 + '@vitest/pretty-format': 2.1.5 '@vitest/runner': 2.1.2 '@vitest/snapshot': 2.1.2 '@vitest/spy': 2.1.2 '@vitest/utils': 2.1.2 - chai: 5.1.1 - debug: 4.3.7 - magic-string: 0.30.11 + chai: 5.1.2 + debug: 4.3.7(supports-color@8.1.1) + magic-string: 0.30.13 pathe: 1.1.2 - std-env: 3.7.0 + std-env: 3.8.0 tinybench: 2.9.0 - tinyexec: 0.3.0 + tinyexec: 0.3.1 tinypool: 1.0.1 tinyrainbow: 1.2.0 vite: 5.4.8(@types/node@22.9.0) @@ -4405,6 +5174,8 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 + workerpool@6.5.1: {} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -4423,8 +5194,7 @@ snapshots: string-width: 5.1.2 strip-ansi: 7.1.0 - wrappy@1.0.2: - optional: true + wrappy@1.0.2: {} xml2js@0.5.0: dependencies: @@ -4433,10 +5203,43 @@ snapshots: xmlbuilder@11.0.1: {} + y18n@5.0.8: {} + yallist@4.0.0: {} yallist@5.0.0: {} + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs-unparser@2.0.0: + dependencies: + camelcase: 6.3.0 + decamelize: 4.0.0 + flat: 5.0.2 + is-plain-obj: 2.1.0 + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yauzl@2.10.0: dependencies: buffer-crc32: 0.2.13 @@ -4451,4 +5254,6 @@ snapshots: dependencies: buffer-crc32: 0.2.13 + yocto-queue@0.1.0: {} + yoctocolors-cjs@2.1.2: {} From b6d5c0f33eba957bb793b0782f7c569174b697b5 Mon Sep 17 00:00:00 2001 From: oxc-bot Date: Wed, 20 Nov 2024 15:45:24 +0800 Subject: [PATCH 052/121] release(oxlint): v0.12.0 (#7366) ## [0.12.0] - 2024-11-20 - 20d9080 linter: [**BREAKING**] Override plugins array when passed in config file (#7303) (camchenry) ### Features - 1d9f528 linter: Implement `unicorn/prefer-string-raw` lint rule (#7335) (Ryan Walker) - d445e0f linter: Implement `unicorn/consistent-existence-index-check` (#7262) (Ryan Walker) - 01ddf37 linter: Add `allowReject` option to `no-useless-promise-resolve-reject` (#7274) (no-yan) - 755a31b linter: Support bind function case for compatibility with `promise/no-return-wrap` (#7232) (no-yan) - 428770e linter: Add `import/no-namespace` rule (#7229) (Dmitry Zakharov) - 9c91151 linter: Implement typescript/no-empty-object-type (#6977) (Orenbek) - 2268a0e linter: Support `overrides` config field (#6974) (DonIsaac) - 3dcac1a linter: React/exhaustive-deps (#7151) (camc314) - d3a0119 oxlint: Add `cwd` property to `LintRunner` (#7352) (Alexander S.) ### Bug Fixes - ba0b2ff editor: Reload workspace configuration after change (#7302) (Alexander S.) - bc0e72c linter: Handle user variables correctly for import/no_commonjs (#7316) (Dmitry Zakharov) - bf839c1 linter: False positive in `jest/expect-expect` (#7341) (dalaoshu) - ff2a1d4 linter: Move `exhaustive-deps` to `react` (#7251) (camc314) - df5c535 linter: Revert unmatched rule error (#7257) (Cameron A McHenry) - c4ed230 linter: Fix false positive in eslint/no-cond-assign (#7241) (camc314) - ef847da linter: False positive in `jsx-a11y/iframe-has-title` (#7253) (dalaoshu) - 62b6327 linter: React/exhaustive-deps update span for unknown deps diagnostic (#7249) (camc314) ### Documentation - 4c124a8 editor/vscode: Update VS Code readme with installation instructions and available features (#7306) (Nicholas Rayburn) ### Refactor - c6a4868 linter: Temporarily remove unknown rules checking (#7260) (camchenry) ### Testing - 5190b7f editor: Add test setup (#7361) (Alexander S.) Co-authored-by: Boshen <1430279+Boshen@users.noreply.github.com> --- Cargo.lock | 4 ++-- apps/oxlint/CHANGELOG.md | 11 +++++++++++ apps/oxlint/Cargo.toml | 2 +- crates/oxc_linter/CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ crates/oxc_linter/Cargo.toml | 2 +- editors/vscode/CHANGELOG.md | 14 ++++++++++++++ editors/vscode/package.json | 2 +- npm/oxlint/CHANGELOG.md | 6 ++++++ npm/oxlint/package.json | 2 +- 9 files changed, 68 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dff09b9f4c9d00..7cb7183c54903a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1700,7 +1700,7 @@ dependencies = [ [[package]] name = "oxc_linter" -version = "0.11.1" +version = "0.12.0" dependencies = [ "aho-corasick", "bitflags 2.6.0", @@ -2123,7 +2123,7 @@ dependencies = [ [[package]] name = "oxlint" -version = "0.11.1" +version = "0.12.0" dependencies = [ "bpaf", "glob", diff --git a/apps/oxlint/CHANGELOG.md b/apps/oxlint/CHANGELOG.md index 5d3173eee354b3..71e77c942eac30 100644 --- a/apps/oxlint/CHANGELOG.md +++ b/apps/oxlint/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0. +## [0.12.0] - 2024-11-20 + +### Features + +- 2268a0e linter: Support `overrides` config field (#6974) (DonIsaac) +- d3a0119 oxlint: Add `cwd` property to `LintRunner` (#7352) (Alexander S.) + +### Bug Fixes + +- df5c535 linter: Revert unmatched rule error (#7257) (Cameron A McHenry) + ## [0.11.0] - 2024-11-03 - 1f2a6c6 linter: [**BREAKING**] Report unmatched rules with error exit code (#7027) (camchenry) diff --git a/apps/oxlint/Cargo.toml b/apps/oxlint/Cargo.toml index 40cd92790b83cf..2601f0450b3b7c 100644 --- a/apps/oxlint/Cargo.toml +++ b/apps/oxlint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "oxlint" -version = "0.11.1" +version = "0.12.0" authors.workspace = true categories.workspace = true edition.workspace = true diff --git a/crates/oxc_linter/CHANGELOG.md b/crates/oxc_linter/CHANGELOG.md index 50248a5f743699..2c0248f73e6fbc 100644 --- a/crates/oxc_linter/CHANGELOG.md +++ b/crates/oxc_linter/CHANGELOG.md @@ -4,6 +4,37 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0. +## [0.12.0] - 2024-11-20 + +- 20d9080 linter: [**BREAKING**] Override plugins array when passed in config file (#7303) (camchenry) + +- 44375a5 ast: [**BREAKING**] Rename `TSEnumMemberName` enum variants (#7250) (overlookmotel) + +### Features + +- 1d9f528 linter: Implement `unicorn/prefer-string-raw` lint rule (#7335) (Ryan Walker) +- d445e0f linter: Implement `unicorn/consistent-existence-index-check` (#7262) (Ryan Walker) +- 01ddf37 linter: Add `allowReject` option to `no-useless-promise-resolve-reject` (#7274) (no-yan) +- 755a31b linter: Support bind function case for compatibility with `promise/no-return-wrap` (#7232) (no-yan) +- 428770e linter: Add `import/no-namespace` rule (#7229) (Dmitry Zakharov) +- 9c91151 linter: Implement typescript/no-empty-object-type (#6977) (Orenbek) +- 2268a0e linter: Support `overrides` config field (#6974) (DonIsaac) +- 3dcac1a linter: React/exhaustive-deps (#7151) (camc314) + +### Bug Fixes + +- bc0e72c linter: Handle user variables correctly for import/no_commonjs (#7316) (Dmitry Zakharov) +- bf839c1 linter: False positive in `jest/expect-expect` (#7341) (dalaoshu) +- ff2a1d4 linter: Move `exhaustive-deps` to `react` (#7251) (camc314) +- df5c535 linter: Revert unmatched rule error (#7257) (Cameron A McHenry) +- c4ed230 linter: Fix false positive in eslint/no-cond-assign (#7241) (camc314) +- ef847da linter: False positive in `jsx-a11y/iframe-has-title` (#7253) (dalaoshu) +- 62b6327 linter: React/exhaustive-deps update span for unknown deps diagnostic (#7249) (camc314) + +### Refactor + +- c6a4868 linter: Temporarily remove unknown rules checking (#7260) (camchenry) + ## [0.11.1] - 2024-11-09 - 0e4adc1 ast: [**BREAKING**] Remove invalid expressions from `TSEnumMemberName` (#7219) (Boshen) diff --git a/crates/oxc_linter/Cargo.toml b/crates/oxc_linter/Cargo.toml index 50a9006ba030a3..3c9e8564580666 100644 --- a/crates/oxc_linter/Cargo.toml +++ b/crates/oxc_linter/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "oxc_linter" -version = "0.11.1" +version = "0.12.0" authors.workspace = true categories.workspace = true edition.workspace = true diff --git a/editors/vscode/CHANGELOG.md b/editors/vscode/CHANGELOG.md index a5b11ed45704a9..d08b80e4e01fd9 100644 --- a/editors/vscode/CHANGELOG.md +++ b/editors/vscode/CHANGELOG.md @@ -4,6 +4,20 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0. +## [0.12.0] - 2024-11-20 + +### Bug Fixes + +- ba0b2ff editor: Reload workspace configuration after change (#7302) (Alexander S.) + +### Documentation + +- 4c124a8 editor/vscode: Update VS Code readme with installation instructions and available features (#7306) (Nicholas Rayburn) + +### Testing + +- 5190b7f editor: Add test setup (#7361) (Alexander S.) + ## [0.11.1] - 2024-11-09 ### Features diff --git a/editors/vscode/package.json b/editors/vscode/package.json index cfb54add0232a9..8d767b904a6d66 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -2,7 +2,7 @@ "name": "oxc-vscode", "description": "oxc vscode extension", "license": "MIT", - "version": "0.11.1", + "version": "0.12.0", "icon": "icon.png", "publisher": "oxc", "displayName": "Oxc", diff --git a/npm/oxlint/CHANGELOG.md b/npm/oxlint/CHANGELOG.md index 98d7573e561863..106bedf3408111 100644 --- a/npm/oxlint/CHANGELOG.md +++ b/npm/oxlint/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this package will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project does not adhere to [Semantic Versioning](https://semver.org/spec/v2.0.0.html) until v1.0.0. +## [0.12.0] - 2024-11-20 + +### Features + +- 2268a0e linter: Support `overrides` config field (#6974) (DonIsaac) + ## [0.11.0] - 2024-11-03 ### Documentation diff --git a/npm/oxlint/package.json b/npm/oxlint/package.json index becd82e44ab7dd..cff4d6e1a10784 100644 --- a/npm/oxlint/package.json +++ b/npm/oxlint/package.json @@ -1,6 +1,6 @@ { "name": "oxlint", - "version": "0.11.1", + "version": "0.12.0", "description": "Linter for the JavaScript Oxidation Compiler", "keywords": [], "author": "Boshen and oxc contributors", From 82773cb455faadea3376756fa247df4c05fc9ba0 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:08:51 +0000 Subject: [PATCH 053/121] feat(codegen): remove underscore from bigint (#7367) closes #7285 closes #7286 --- crates/oxc_codegen/src/gen.rs | 6 +- crates/oxc_codegen/tests/integration/unit.rs | 65 +++++++++++++++++++ .../tests/snapshots/as-const.snap | 3 +- .../tests/snapshots/infer-expression.snap | 3 +- 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index cbb5409f6988e2..e2f7cc6dd2105c 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -1163,12 +1163,14 @@ impl<'a> GenExpr for NumericLiteral<'a> { impl<'a> Gen for BigIntLiteral<'a> { fn gen(&self, p: &mut Codegen, _ctx: Context) { - if self.raw.starts_with('-') { + let raw = self.raw.as_str().cow_replace('_', ""); + if raw.starts_with('-') { p.print_space_before_operator(Operator::Unary(UnaryOperator::UnaryNegation)); } + p.print_space_before_identifier(); p.add_source_mapping(self.span.start); - p.print_str(self.raw.as_str()); + p.print_str(&raw); } } diff --git a/crates/oxc_codegen/tests/integration/unit.rs b/crates/oxc_codegen/tests/integration/unit.rs index 17cf30bbea8aab..dae518dd5bcab2 100644 --- a/crates/oxc_codegen/tests/integration/unit.rs +++ b/crates/oxc_codegen/tests/integration/unit.rs @@ -301,3 +301,68 @@ fn in_expr_in_arrow_function_expression() { test("() => 'foo' in bar", "() => \"foo\" in bar;\n"); test("() => { ('foo' in bar) }", "() => {\n\t\"foo\" in bar;\n};\n"); } + +#[test] +fn big_int() { + test("9007199254740991n;", "9007199254740991n;\n"); + test("-9007199254740991n;", "-9007199254740991n;\n"); + test("-90_0719_92547_40991n;", "-9007199254740991n;\n"); + test("+9007199254740991n;", "+9007199254740991n;\n"); + test("1000n", "1000n;\n"); + test("-15n", "-15n;\n"); + + test("100_000_000n;", "100000000n;\n"); + test("10000000000000000n;", "10000000000000000n;\n"); + test("0n;", "0n;\n"); + test("+0n;", "+0n;\n"); + test("-0n;", "-0n;\n"); + + test("0x1_0n;", "0x10n;\n"); + test("0x10n;", "0x10n;\n"); + + test("0b1_01n;", "0b101n;\n"); + test("0b101n;", "0b101n;\n"); + test("0b101_101n;", "0b101101n;\n"); + test("0b10_1n", "0b101n;\n"); + + test("0o13n;", "0o13n;\n"); + test("0o7n", "0o7n;\n"); + + test("0x2_0n", "0x20n;\n"); + test("0xfabn", "0xfabn;\n"); + test("0xaef_en;", "0xaefen;\n"); + test("0xaefen;", "0xaefen;\n"); +} + +#[test] +#[ignore = "Minify bigint is not implemented."] +fn big_int_minify() { + test_minify("9007199254740991n", "9007199254740991n;"); + test_minify("-9007199254740991n;", "-9007199254740991n;"); + test_minify("-90_0719_92547_40991n;", "-9007199254740991n;"); + test_minify("+9007199254740991n;", "+9007199254740991n;"); + test_minify("1000n", "1000n;"); + test_minify("-15n", "-15n;"); + + test_minify("100_000_000n;", "100000000n;"); + test_minify("10000000000000000n;", "0x2386f26fc10000n;"); + test_minify("0n;", "0n;"); + test_minify("+0n;", "+0n;"); + test_minify("-0n;", "-0n;"); + + test_minify("0x1_0n;", "16n;"); + test_minify("0x10n;", "16n;"); + + test_minify("0b1_01n;", "5n;"); + test_minify("0b101n;", "5n;"); + test_minify("0b101_101n;", "45n;"); + test_minify("0b10_1n", "5n;"); + + test_minify("0o13n;", "11n;"); + test_minify("0o7n", "7n;"); + + test_minify("0x2_0n", "32n;"); + test_minify("0xfabn", "4011n;"); + test_minify("0xaef_en;", "44798n;"); + test_minify("0xaefen;", "44798n;"); +} diff --git a/crates/oxc_isolated_declarations/tests/snapshots/as-const.snap b/crates/oxc_isolated_declarations/tests/snapshots/as-const.snap index edb2066d8a11e5..db05afc0f607de 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/as-const.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/as-const.snap @@ -1,6 +1,7 @@ --- source: crates/oxc_isolated_declarations/tests/mod.rs input_file: crates/oxc_isolated_declarations/tests/fixtures/as-const.ts +snapshot_kind: text --- ``` ==================== .D.TS ==================== @@ -9,7 +10,7 @@ declare const F: { readonly string: "string"; readonly templateLiteral: "templateLiteral"; readonly number: 1.23; - readonly bigint: -1_2_3n; + readonly bigint: -123n; readonly boolean: true; readonly null: null; readonly undefined: undefined; diff --git a/crates/oxc_isolated_declarations/tests/snapshots/infer-expression.snap b/crates/oxc_isolated_declarations/tests/snapshots/infer-expression.snap index 6a49c344a90bf2..3ce34e4905d038 100644 --- a/crates/oxc_isolated_declarations/tests/snapshots/infer-expression.snap +++ b/crates/oxc_isolated_declarations/tests/snapshots/infer-expression.snap @@ -1,6 +1,7 @@ --- source: crates/oxc_isolated_declarations/tests/mod.rs input_file: crates/oxc_isolated_declarations/tests/fixtures/infer-expression.ts +snapshot_kind: text --- ``` ==================== .D.TS ==================== @@ -10,7 +11,7 @@ declare const s: string; declare const t: string; declare const b: boolean; declare let unaryA: number; -declare const unaryB = -1_2n; +declare const unaryB = -12n; declare const unaryC: unknown; declare const unaryD: unknown; declare const unaryE: {}; From 9b9d02078cb937013bcb686e44b855a9ee4db196 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:18:25 +0000 Subject: [PATCH 054/121] docs(semantic): document the meaning of `ReferenceFlags::Read` and `Write` (#7368) closes #5165 --- crates/oxc_syntax/src/reference.rs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/crates/oxc_syntax/src/reference.rs b/crates/oxc_syntax/src/reference.rs index 67d4df85cbbda0..1f80be19530028 100644 --- a/crates/oxc_syntax/src/reference.rs +++ b/crates/oxc_syntax/src/reference.rs @@ -76,9 +76,31 @@ bitflags! { #[cfg_attr(feature = "serialize", derive(Serialize))] pub struct ReferenceFlags: u8 { const None = 0; - /// A symbol is being read as a Value + /// A symbol is being read as a Value. + /// + /// This value can be derived from the spec: + /// + /// Under `Runtime Semantics: Evaluation`, when [`GetValue`](https://tc39.es/ecma262/#sec-getvalue) is called + /// on a expression, and the expression is an `IdentifierReference`. + /// + /// For example: + /// ```text + /// 1. Let lRef be ? Evaluation of Expression. + /// 2. Perform ? GetValue(lRef). + /// ``` const Read = 1 << 0; /// A symbol is being written to in a Value context. + /// + /// This value can be derived from the spec: + /// + /// Under `Runtime Semantics: Evaluation`, when [`PutValue`](https://tc39.es/ecma262/#sec-putvalue) is called + /// on a expression, and the expression is an `IdentifierReference`. + /// + /// For example: + /// ```text + /// 1. Let lhs be ?Β Evaluation of LeftHandSideExpression. + /// 2. Perform ?Β PutValue(lhs, newValue). + /// ``` const Write = 1 << 1; /// Used in type definitions. const Type = 1 << 2; From b3965bbff0aa95641608e5b51350e14e2e1e8b5b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Nov 2024 17:26:48 +0800 Subject: [PATCH 055/121] chore(deps): update npm packages (#7364) --- package.json | 2 +- pnpm-lock.yaml | 585 ++++++++++-------- .../snapshots/babel_exec.snap.md | 10 +- 3 files changed, 338 insertions(+), 259 deletions(-) diff --git a/package.json b/package.json index fb94952764a4ae..006deb61eeccf8 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "oxc", "private": true, - "packageManager": "pnpm@9.12.3", + "packageManager": "pnpm@9.14.1", "volta": { "node": "22.11.0" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index e7c77ba9d629cd..6df40c125710d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,19 +4,31 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +catalogs: + default: + '@napi-rs/cli': + specifier: 3.0.0-alpha.61 + version: 3.0.0-alpha.61 + typescript: + specifier: 5.6.3 + version: 5.6.3 + vitest: + specifier: 2.1.2 + version: 2.1.2 + importers: .: devDependencies: '@napi-rs/cli': specifier: 'catalog:' - version: 3.0.0-alpha.61(@emnapi/runtime@1.2.0) + version: 3.0.0-alpha.61(@emnapi/runtime@1.3.1) typescript: specifier: 'catalog:' version: 5.6.3 vitest: specifier: 'catalog:' - version: 2.1.2(@types/node@22.9.0) + version: 2.1.2(@types/node@22.9.1) editors/vscode: dependencies: @@ -29,7 +41,7 @@ importers: version: 10.0.9 '@types/node': specifier: ^22.0.0 - version: 22.9.0 + version: 22.9.1 '@types/vscode': specifier: 1.95.0 version: 1.95.0 @@ -78,6 +90,12 @@ importers: npm/oxc-types: {} + npm/oxc-wasm: + dependencies: + '@oxc-project/types': + specifier: workspace:^ + version: link:../oxc-types + npm/oxlint: {} npm/parser-wasm: @@ -169,11 +187,11 @@ packages: '@bcoe/v8-coverage@0.2.3': resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} - '@emnapi/core@1.2.0': - resolution: {integrity: sha512-E7Vgw78I93we4ZWdYCb4DGAwRROGkMIXk7/y87UmANR+J6qsWusmC3gLt0H+O0KOt5e6O38U8oJamgbudrES/w==} + '@emnapi/core@1.3.1': + resolution: {integrity: sha512-pVGjBIt1Y6gg3EJN8jTcfpP/+uuRksIo055oE/OBkDNcjZqVbfkWCksG1Jp4yZnj3iKWyWX8fdG/j6UDYPbFog==} - '@emnapi/runtime@1.2.0': - resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} + '@emnapi/runtime@1.3.1': + resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} '@emnapi/wasi-threads@1.0.1': resolution: {integrity: sha512-iIBu7mwkq4UQGeMEM8bLwNK962nXdhodeScX4slfQnRhEMMzvYivHhutCIk8uojvmASXXPC2WNEjwxFWk72Oqw==} @@ -468,20 +486,20 @@ packages: resolution: {integrity: sha512-oOIwPs0Dvq5220Z8lGL/6LHRTEr9TgLHmiI99Rj1PJ1p1czTys+olrgBqZk4E2qC0YTzeHprxSQmoHioVdJ7Lw==} engines: {node: '>=18'} - '@inquirer/core@9.1.0': - resolution: {integrity: sha512-RZVfH//2ytTjmaBIzeKT1zefcQZzuruwkpTwwbe/i2jTl4o9M+iML5ChULzz6iw1Ok8iUBBsRCjY2IEbD8Ft4w==} + '@inquirer/core@9.2.1': + resolution: {integrity: sha512-F2VBt7W/mwqEU4bL0RnHNZmC/OxzNx9cOYxHqnXX3MP6ruYvZUZAW9imgN9+h/uBT/oP8Gh888J2OZSbjSeWcg==} engines: {node: '>=18'} '@inquirer/editor@2.2.0': resolution: {integrity: sha512-9KHOpJ+dIL5SZli8lJ6xdaYLPPzB8xB9GZItg39MBybzhxA16vxmszmQFrRwbOA918WA2rvu8xhDEg/p6LXKbw==} engines: {node: '>=18'} - '@inquirer/expand@2.2.0': - resolution: {integrity: sha512-PD0z1dTRTIlpcnXRMRvdVPfBe10jBf4i7YLBU8tNWDkf3HxqmdymVvqnT8XG+hxQSvqfpJCe13Jv2Iv1eB3bIg==} + '@inquirer/expand@2.3.0': + resolution: {integrity: sha512-qnJsUcOGCSG1e5DTOErmv2BPQqrtT6uzqn1vI/aYGiPKq+FgslGZmtdnXbhuI7IlT7OByDoEEqdnhUnVR2hhLw==} engines: {node: '>=18'} - '@inquirer/figures@1.0.5': - resolution: {integrity: sha512-79hP/VWdZ2UVc9bFGJnoQ/lQMpL74mGgzSYX1xUqCVk7/v73vJCMw1VuyWN1jGkZ9B3z7THAbySqGbCNefcjfA==} + '@inquirer/figures@1.0.8': + resolution: {integrity: sha512-tKd+jsmhq21AP1LhexC0pPwsCxEhGgAkg28byjJAd+xhmIs8LUX8JbUc3vBf3PhLxWiB5EvyBE5X7JSPAqMAqg==} engines: {node: '>=18'} '@inquirer/input@2.3.0': @@ -496,8 +514,8 @@ packages: resolution: {integrity: sha512-5otqIpgsPYIshqhgtEwSspBQE40etouR8VIxzpJkv9i0dVHIpyhiivbkH9/dGiMLdyamT54YRdGJLfl8TFnLHg==} engines: {node: '>=18'} - '@inquirer/prompts@5.4.0': - resolution: {integrity: sha512-HIQGd7JOX6WXf7zg7WGs+1m+e3eRFyL4mDtWRlV01AXqZido9W3BSoku2BR4E1lK/NCXok6jg6tTcLw4I0thfg==} + '@inquirer/prompts@5.5.0': + resolution: {integrity: sha512-BHDeL0catgHdcHbSFFUddNzvx/imzJMft+tWDPwTm3hfu8/tApk1HrooNngB2Mb4qY+KaRWF+iZqoVUPeslEog==} engines: {node: '>=18'} '@inquirer/rawlist@2.3.0': @@ -512,8 +530,12 @@ packages: resolution: {integrity: sha512-YmDobTItPP3WcEI86GvPo+T2sRHkxxOq/kXmsBjHS5BVXUgvgZ5AfJjkvQvZr03T81NnI3KrrRuMzeuYUQRFOA==} engines: {node: '>=18'} - '@inquirer/type@1.5.3': - resolution: {integrity: sha512-xUQ14WQGR/HK5ei+2CvgcwoH9fQ4PgPGmVFSN0pc1+fVyDL3MREhyAY7nxEErSu6CkllBM3D7e3e+kOvtu+eIg==} + '@inquirer/type@1.5.5': + resolution: {integrity: sha512-MzICLu4yS7V8AA61sANROZ9vT1H3ooca5dSmI1FjZkzq7o/koMsRfQSzRtFo+F3Ao4Sf1C0bpLKejpKB/+j6MA==} + engines: {node: '>=18'} + + '@inquirer/type@2.0.0': + resolution: {integrity: sha512-XvJRx+2KR3YXyYtPUUy+qd9i7p+GO9Ko6VIIpWlBrpWwXDv8WLFeHTxz35CfQFUiBMLXlGHhGzys7lqit9gWag==} engines: {node: '>=18'} '@isaacs/cliui@8.0.2': @@ -574,91 +596,109 @@ packages: '@napi-rs/cross-toolchain-x64-target-x86_64': optional: true - '@napi-rs/lzma-android-arm-eabi@1.3.1': - resolution: {integrity: sha512-mtGOg8jXlc+pTBI86cqohfndS9UmOAkk9d5CChKMb8btVks70yhUN1e7YYS3QFbmoxbPs2Ee+wmuH1Khdc7B2w==} + '@napi-rs/lzma-android-arm-eabi@1.4.1': + resolution: {integrity: sha512-yenreSpZ9IrqppJOiWDqWMmja7XtSgio9LhtxYwgdILmy/OJTe/mlTYv+FhJBf7hIV9Razu5eBuEa3zKri81IA==} engines: {node: '>= 10'} cpu: [arm] os: [android] - '@napi-rs/lzma-android-arm64@1.3.1': - resolution: {integrity: sha512-4uGkQgAv9Tnc/i0k2eIgbhZgyzs94+iECWxz4MFZNcZ1fNGvGbRL2j+SITE4OmwrUn3TuFK/uYWfgzooq8E1Qg==} + '@napi-rs/lzma-android-arm64@1.4.1': + resolution: {integrity: sha512-piutVBz5B1TNxXeEjub0n/IKI6dMaXPPRbVSXuc4gnZgzcihNDUh68vcLZgYd+IMiACZvBxvx2O3t5nthtph3A==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@napi-rs/lzma-darwin-arm64@1.3.1': - resolution: {integrity: sha512-MZBg4iwHTS8icjTiCMdzh8kYrMmKBCEglFPa+vjI91R2XDwuuwSzqmpATRpmMH8cWUUWtGPF4fnxKzjgkzhd4Q==} + '@napi-rs/lzma-darwin-arm64@1.4.1': + resolution: {integrity: sha512-sDfOhQQFqV8lGbpgJN9DqNLBPR7QOfYjcWUv8FOGPaVP1LPJDnrc5uCpRWWEa2zIKmTiO8P9xzIl0TDzrYmghg==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@napi-rs/lzma-darwin-x64@1.3.1': - resolution: {integrity: sha512-7vte+1lYV7xgZERKH/pjAeh4T16aQASKOzu4op70pK6VP/64Plr5rrvqxQqQmlAIe4pwyo/RkFl1n4LXDod3xg==} + '@napi-rs/lzma-darwin-x64@1.4.1': + resolution: {integrity: sha512-S5/RbC6EP4QkYy2xhxbfm48ZD9FkysfpWY4Slve0nj5RGGsHvcJBg2Pi69jrTPB/zLKz2SUa0i+RfUt9zvZNaw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@napi-rs/lzma-freebsd-x64@1.3.1': - resolution: {integrity: sha512-uBS74fynTqLUC3catIxyezCafn8UDlr2yxVV47vz1T6Vop2PGDz/cMQdV6rnLSjPE08Rv66ihM36mgf/MmOkOg==} + '@napi-rs/lzma-freebsd-x64@1.4.1': + resolution: {integrity: sha512-4AFnq6aZnclwameSBkDWu5Ftb8y4GwvVXeQXJKbN7hf7O5GG/8QpQB1R1NJw2QORUhpKwjAQUpbkTyhL2GFWWw==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@napi-rs/lzma-linux-arm-gnueabihf@1.3.1': - resolution: {integrity: sha512-rrVLyqBJeN29gPJCNkPbZ7dAzaseEcERKyhjwM+DfbFrDUvtkEcrYPvo+iwE/NmF+OkZQkzcanrVMGnq/mcJYQ==} + '@napi-rs/lzma-linux-arm-gnueabihf@1.4.1': + resolution: {integrity: sha512-j5rL1YRIm6rWmmGAvN6DPX6QuRjvFGB93xJ7DTRB47GXW4zHekXae6ivowjJ95vT4Iz4hSWkZbuwAy95eFrWRA==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@napi-rs/lzma-linux-arm64-gnu@1.3.1': - resolution: {integrity: sha512-vDmVsthRbX2opkgRirJJGKQxUP/spvyVM2Y5CyCWZ7sadSID3hA97r38gf9ISn/sJ8/r93IPWLq+iycudNKi+Q==} + '@napi-rs/lzma-linux-arm64-gnu@1.4.1': + resolution: {integrity: sha512-1XdFGKyTS9m+VrRQYs9uz+ToHf4Jwm0ejHU48k9lT9MPl8jSqzKdVtFzZBPzronHteSynBfKmUq0+HeWmjrsOQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/lzma-linux-arm64-musl@1.3.1': - resolution: {integrity: sha512-x4m/J3hRdFd3IoqKc+4aBcSUkcuDEP7hH6vdss8bKNLjPfXmnG/lcHJEQX3hNnNOULPP8xVRxgiY8jeL62cnsw==} + '@napi-rs/lzma-linux-arm64-musl@1.4.1': + resolution: {integrity: sha512-9d09tYS0/rBwIk1QTcO2hMZEB/ZpsG2+uFW5am1RHElSWMclObirB1An7b6AMDJcRvcomkOg2GZ9COzrvHKwEA==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@napi-rs/lzma-linux-x64-gnu@1.3.1': - resolution: {integrity: sha512-riB+Xg72NfH8Kcpq07omshVu0QsLW0v2bhywBNYxvA+t2dGGWSIEN1U/zazUXys+IEA6pBQKqLVseurWE6Cl8g==} + '@napi-rs/lzma-linux-ppc64-gnu@1.4.1': + resolution: {integrity: sha512-UzEkmsgoJ3IOGIRb6kBzNiw+ThUpiighop7dVYfSqlF5juGzwf7YewC57RGn4FoJCvadOCrSm5VikAcgrwVgAw==} + engines: {node: '>= 10'} + cpu: [ppc64] + os: [linux] + + '@napi-rs/lzma-linux-riscv64-gnu@1.4.1': + resolution: {integrity: sha512-9dUKlZ1PdwxTaFF+j3oc+xjlk9nqFwo1NWWOH30uwjl4Rm5Gkv+Fx0pHrzu4kR/iVA+oyQqa9/2uDYnGSTijBA==} + engines: {node: '>= 10'} + cpu: [riscv64] + os: [linux] + + '@napi-rs/lzma-linux-s390x-gnu@1.4.1': + resolution: {integrity: sha512-MOVXUWJSLLCJDCCAlGa39sh7nv9XjvXzCf7QJus7rD8Ciz0mpXNXF9mg0ji7/MZ7pZlKPlXjXDnpVCfFdSEaFQ==} + engines: {node: '>= 10'} + cpu: [s390x] + os: [linux] + + '@napi-rs/lzma-linux-x64-gnu@1.4.1': + resolution: {integrity: sha512-Sxu7aJxU1sDbUTqjqLVDV3DCOAlbsFKvmuCN/S5uXBJd1IF2wJ9jK3NbFzfqTAo5Hudx8Y7kOb6+3K+fYPI1KQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/lzma-linux-x64-musl@1.3.1': - resolution: {integrity: sha512-JXLgJFwoeysxdSg7rdVYP8wrliCQVJlU5JcLYjRVSCL4P0mQTjnYi7R7VdaOkDACw/Fvlji7oIJXt0KiaDTcOw==} + '@napi-rs/lzma-linux-x64-musl@1.4.1': + resolution: {integrity: sha512-4I3BeKBQJSE5gF2/VTEv7wCLLjhapeutbCGpZPmDiLHZ74rm9edmNXAlKpdjADQ4YDLJ2GIBzttvwLXkJ9U+cw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@napi-rs/lzma-wasm32-wasi@1.3.1': - resolution: {integrity: sha512-XTA9XTUtj0KPKuzNS2oi3bWN6tJodk00wwMd/TiKoEqx9Fe/zu+OfDGuXAn+xs+P7S3YCDHqjYinuTQMZ0ucJw==} + '@napi-rs/lzma-wasm32-wasi@1.4.1': + resolution: {integrity: sha512-s32HdKqQWbohf6DGWpG9YMODaBdbKJ++JpNr6Ii7821sKf4h/o+p8IRFTOaWdmdJdllEWlRirnd5crA29VivJQ==} engines: {node: '>=14.0.0'} cpu: [wasm32] - '@napi-rs/lzma-win32-arm64-msvc@1.3.1': - resolution: {integrity: sha512-qLDfs9UEtLPPTN/FdSz3gSdlx86VwFQBuLBrQtaiYQtUTKZCOYV1Z1fXqFt5Zqa1HKV2oyXnwGcTI7RpcyXxtg==} + '@napi-rs/lzma-win32-arm64-msvc@1.4.1': + resolution: {integrity: sha512-ISz+v7ML5mKnjEZ7Kk4Z1BIn411r/fz3tDy9j5yDnwQI0MgTsUQFrIQElGUpULWYs2aYc6EZ9PhECbLBfSjh7A==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@napi-rs/lzma-win32-ia32-msvc@1.3.1': - resolution: {integrity: sha512-rWNlxLFMIfvxzfdQCfeQ3D/HEnQG3vfladFYrXUx6ePXO6r+BLCGn6/LWSSuKlw4vKkb1iHEWsAVaRLIcJEMIA==} + '@napi-rs/lzma-win32-ia32-msvc@1.4.1': + resolution: {integrity: sha512-3WKuCpZBrd7Jrw+h1jSu5XAsRWepMJu0sYuRoA4Y4Cwfu9gI7p5Z5Bc510nfjg7M7xvdpkI4UoW2WY7kBFRYrQ==} engines: {node: '>= 10'} cpu: [ia32] os: [win32] - '@napi-rs/lzma-win32-x64-msvc@1.3.1': - resolution: {integrity: sha512-SNfHNqEjabXfTL1+KRi0qiAhwIlZHhQystvfSYX6p1g+2trSC/3WUpUQ4fbbR7KyE31g2AAnwjXivnlQ0af/pg==} + '@napi-rs/lzma-win32-x64-msvc@1.4.1': + resolution: {integrity: sha512-0ixRo5z1zFXdh62hlrTV+QCTKHK0te5NHKaExOluhtcc6AdpMmpslvM9JhUxNHI+zM46w/DmmcvcOtqsaTmHgg==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@napi-rs/lzma@1.3.1': - resolution: {integrity: sha512-XyZoBlYNMvCulK/RmVK/0nB3j7IdH7HpqcrMMg0U+HqQqKRLOQBwvnKNBocPC1bZQ7iZuKWYTLn1ayZwTyek8w==} + '@napi-rs/lzma@1.4.1': + resolution: {integrity: sha512-5f8K9NHjwHjZKGm3SS+7CFxXQhz8rbg2umBm/9g0xQRXBdYEI31N5z1ACuk9bmBQOusXAq9CArGfs/ZQso2rUA==} engines: {node: '>= 10'} '@napi-rs/tar-android-arm-eabi@0.1.4': @@ -760,8 +800,8 @@ packages: resolution: {integrity: sha512-hDsvmMZY8tl2CcLfjnTeE1o5W1eGTSL+ZIX8YEybtcJwA+Cc8SNHb7l6JqMnGcjOrWBZbHt8tzTN+W7qHS5Wmg==} engines: {node: '>= 10'} - '@napi-rs/wasm-runtime@0.2.4': - resolution: {integrity: sha512-9zESzOO5aDByvhIAsOy9TbpZ0Ur2AJbUI7UT73kcUTS2mxAMHOBaa1st/jAymNoCtvrit99kkzT1FZuXVcgfIQ==} + '@napi-rs/wasm-runtime@0.2.5': + resolution: {integrity: sha512-kwUxR7J9WLutBbulqg1dfOrMTwhMdXLdcGUhcbCcGwnPLt3gz19uHVdwH1syKVDbE022ZS2vZxOWflFLS0YTjw==} '@napi-rs/wasm-tools-android-arm-eabi@0.0.2': resolution: {integrity: sha512-/b+UU3suXjW4P0DzHRNdrnebQtFKcQf/YMeZJH+xUlKgvwli5kbmWjx8Wqqz0VETVkUTuPqJMBDIVLyc+14FGw==} @@ -863,8 +903,8 @@ packages: '@octokit/openapi-types@22.2.0': resolution: {integrity: sha512-QBhVjcUa9W7Wwhm6DBFu6ZZ+1/t/oYxqc2tp81Pi41YNuJinbFRx8B133qVOrAaBbF7D/m0Et6f9/pZt9Rc+tg==} - '@octokit/plugin-paginate-rest@11.3.3': - resolution: {integrity: sha512-o4WRoOJZlKqEEgj+i9CpcmnByvtzoUYC6I8PD2SA95M+BJ2x8h7oLcVOg9qcowWXBOdcTRsMZiwvM3EyLm9AfA==} + '@octokit/plugin-paginate-rest@11.3.5': + resolution: {integrity: sha512-cgwIRtKrpwhLoBi0CUNuY83DPGRMaWVjqVI/bGKsLJ4PzyWZNaEmhHroI2xlrVXkk6nFv0IsZpOp+ZWSWUS2AQ==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' @@ -875,14 +915,14 @@ packages: peerDependencies: '@octokit/core': '>=6' - '@octokit/plugin-rest-endpoint-methods@13.2.4': - resolution: {integrity: sha512-gusyAVgTrPiuXOdfqOySMDztQHv6928PQ3E4dqVGEtOvRXAKRbJR4b1zQyniIT9waqaWk/UDaoJ2dyPr7Bk7Iw==} + '@octokit/plugin-rest-endpoint-methods@13.2.6': + resolution: {integrity: sha512-wMsdyHMjSfKjGINkdGKki06VEkgdEldIGstIEyGX0wbYHGByOwN/KiM+hAAlUwAtPkP3gvXtVQA9L3ITdV2tVw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' - '@octokit/request-error@6.1.4': - resolution: {integrity: sha512-VpAhIUxwhWZQImo/dWAN/NpPqqojR6PSLgLYAituLM6U+ddx9hCioFGwBr5Mi+oi5CLeJkcAs3gJ0PYYzU6wUg==} + '@octokit/request-error@6.1.5': + resolution: {integrity: sha512-IlBTfGX8Yn/oFPMwSfvugfncK2EwRLjzbrpifNaMY8o/HTEAFqCA1FZxjD9cWvSKBHgrIhc4CSBIzMxiLsbzFQ==} engines: {node: '>= 18'} '@octokit/request@9.1.3': @@ -893,8 +933,8 @@ packages: resolution: {integrity: sha512-+CiLisCoyWmYicH25y1cDfCrv41kRSvTq6pPWtRroRJzhsCZWZyCqGyI8foJT5LmScADSwRAnr/xo+eewL04wQ==} engines: {node: '>= 18'} - '@octokit/types@13.5.0': - resolution: {integrity: sha512-HdqWTf5Z3qwDVlzCrP8UJquMwunpDiMPt5er+QjGzL4hqr/vBVY/MauQgS1xWxCDT1oMx1EULyqxncdCY/NVSQ==} + '@octokit/types@13.6.1': + resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==} '@oxlint/darwin-arm64@0.11.1': resolution: {integrity: sha512-S+cHn49fT+qSJXhQ3Z4EG/5ENp2dAUbS2sMNkhgkLqlO8aYl0TR9R7omU3vpU/beu8ePnV+mdVlJYGjsPIMGtg==} @@ -940,83 +980,93 @@ packages: resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} - '@rollup/rollup-android-arm-eabi@4.24.0': - resolution: {integrity: sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==} + '@rollup/rollup-android-arm-eabi@4.27.3': + resolution: {integrity: sha512-EzxVSkIvCFxUd4Mgm4xR9YXrcp976qVaHnqom/Tgm+vU79k4vV4eYTjmRvGfeoW8m9LVcsAy/lGjcgVegKEhLQ==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.24.0': - resolution: {integrity: sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==} + '@rollup/rollup-android-arm64@4.27.3': + resolution: {integrity: sha512-LJc5pDf1wjlt9o/Giaw9Ofl+k/vLUaYsE2zeQGH85giX2F+wn/Cg8b3c5CDP3qmVmeO5NzwVUzQQxwZvC2eQKw==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.24.0': - resolution: {integrity: sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==} + '@rollup/rollup-darwin-arm64@4.27.3': + resolution: {integrity: sha512-OuRysZ1Mt7wpWJ+aYKblVbJWtVn3Cy52h8nLuNSzTqSesYw1EuN6wKp5NW/4eSre3mp12gqFRXOKTcN3AI3LqA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.24.0': - resolution: {integrity: sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==} + '@rollup/rollup-darwin-x64@4.27.3': + resolution: {integrity: sha512-xW//zjJMlJs2sOrCmXdB4d0uiilZsOdlGQIC/jjmMWT47lkLLoB1nsNhPUcnoqyi5YR6I4h+FjBpILxbEy8JRg==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': - resolution: {integrity: sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==} + '@rollup/rollup-freebsd-arm64@4.27.3': + resolution: {integrity: sha512-58E0tIcwZ+12nK1WiLzHOD8I0d0kdrY/+o7yFVPRHuVGY3twBwzwDdTIBGRxLmyjciMYl1B/U515GJy+yn46qw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.27.3': + resolution: {integrity: sha512-78fohrpcVwTLxg1ZzBMlwEimoAJmY6B+5TsyAZ3Vok7YabRBUvjYTsRXPTjGEvv/mfgVBepbW28OlMEz4w8wGA==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.27.3': + resolution: {integrity: sha512-h2Ay79YFXyQi+QZKo3ISZDyKaVD7uUvukEHTOft7kh00WF9mxAaxZsNs3o/eukbeKuH35jBvQqrT61fzKfAB/Q==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.24.0': - resolution: {integrity: sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==} + '@rollup/rollup-linux-arm-musleabihf@4.27.3': + resolution: {integrity: sha512-Sv2GWmrJfRY57urktVLQ0VKZjNZGogVtASAgosDZ1aUB+ykPxSi3X1nWORL5Jk0sTIIwQiPH7iE3BMi9zGWfkg==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.24.0': - resolution: {integrity: sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==} + '@rollup/rollup-linux-arm64-gnu@4.27.3': + resolution: {integrity: sha512-FPoJBLsPW2bDNWjSrwNuTPUt30VnfM8GPGRoLCYKZpPx0xiIEdFip3dH6CqgoT0RnoGXptaNziM0WlKgBc+OWQ==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.24.0': - resolution: {integrity: sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==} + '@rollup/rollup-linux-arm64-musl@4.27.3': + resolution: {integrity: sha512-TKxiOvBorYq4sUpA0JT+Fkh+l+G9DScnG5Dqx7wiiqVMiRSkzTclP35pE6eQQYjP4Gc8yEkJGea6rz4qyWhp3g==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': - resolution: {integrity: sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==} + '@rollup/rollup-linux-powerpc64le-gnu@4.27.3': + resolution: {integrity: sha512-v2M/mPvVUKVOKITa0oCFksnQQ/TqGrT+yD0184/cWHIu0LoIuYHwox0Pm3ccXEz8cEQDLk6FPKd1CCm+PlsISw==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.24.0': - resolution: {integrity: sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==} + '@rollup/rollup-linux-riscv64-gnu@4.27.3': + resolution: {integrity: sha512-LdrI4Yocb1a/tFVkzmOE5WyYRgEBOyEhWYJe4gsDWDiwnjYKjNs7PS6SGlTDB7maOHF4kxevsuNBl2iOcj3b4A==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.24.0': - resolution: {integrity: sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==} + '@rollup/rollup-linux-s390x-gnu@4.27.3': + resolution: {integrity: sha512-d4wVu6SXij/jyiwPvI6C4KxdGzuZOvJ6y9VfrcleHTwo68fl8vZC5ZYHsCVPUi4tndCfMlFniWgwonQ5CUpQcA==} cpu: [s390x] os: [linux] - '@rollup/rollup-linux-x64-gnu@4.24.0': - resolution: {integrity: sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==} + '@rollup/rollup-linux-x64-gnu@4.27.3': + resolution: {integrity: sha512-/6bn6pp1fsCGEY5n3yajmzZQAh+mW4QPItbiWxs69zskBzJuheb3tNynEjL+mKOsUSFK11X4LYF2BwwXnzWleA==} cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.24.0': - resolution: {integrity: sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==} + '@rollup/rollup-linux-x64-musl@4.27.3': + resolution: {integrity: sha512-nBXOfJds8OzUT1qUreT/en3eyOXd2EH5b0wr2bVB5999qHdGKkzGzIyKYaKj02lXk6wpN71ltLIaQpu58YFBoQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.24.0': - resolution: {integrity: sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==} + '@rollup/rollup-win32-arm64-msvc@4.27.3': + resolution: {integrity: sha512-ogfbEVQgIZOz5WPWXF2HVb6En+kWzScuxJo/WdQTqEgeyGkaa2ui5sQav9Zkr7bnNCLK48uxmmK0TySm22eiuw==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.24.0': - resolution: {integrity: sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==} + '@rollup/rollup-win32-ia32-msvc@4.27.3': + resolution: {integrity: sha512-ecE36ZBMLINqiTtSNQ1vzWc5pXLQHlf/oqGp/bSbi7iedcjcNb6QbCBNG73Euyy2C+l/fn8qKWEwxr+0SSfs3w==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.24.0': - resolution: {integrity: sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==} + '@rollup/rollup-win32-x64-msvc@4.27.3': + resolution: {integrity: sha512-vliZLrDmYKyaUoMzEbMTg2JkerfBjn03KmAw9CykO0Zzkzoyd7o3iZNam/TpyWNjNT+Cz2iO3P9Smv2wgrR+Eg==} cpu: [x64] os: [win32] @@ -1035,8 +1085,8 @@ packages: '@types/mute-stream@0.0.4': resolution: {integrity: sha512-CPM9nzrCPPJHQNA9keH9CVkVI+WR5kMa+7XEs5jcGQ0VoAGnLv242w8lIVgwAEfmE4oufJRaTc9PNLQl0ioAow==} - '@types/node@22.9.0': - resolution: {integrity: sha512-vuyHg81vvWA1Z1ELfvLko2c8f34gyA0zaic0+Rllc5lbCnbSyuvb2Oxpm6TAUAC/2xZN3QGqxBNggD1nNR2AfQ==} + '@types/node@22.9.1': + resolution: {integrity: sha512-p8Yy/8sw1caA8CdRIQBG5tiLHmxtQKObCijiAa9Ez+d4+PRffM4054xbju0msf+cvhJpnFEeNjxmVT/0ipktrg==} '@types/vscode@1.95.0': resolution: {integrity: sha512-0LBD8TEiNbet3NvWsmn59zLzOFu/txSlGxnv5yAFHCrhG9WvAnR3IvfHzMOs2aeWqgvNjq9pO99IUw8d3n+unw==} @@ -1751,8 +1801,8 @@ packages: ini@1.3.8: resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} - inquirer@10.2.0: - resolution: {integrity: sha512-OE/HDYrQAgeUPs3mKetfarr/EFiotdULUc7R2XvwqPHMEjFtCqNsfYDfCZ5baAKKtb9kCaKclNTTE9hSi7JFjg==} + inquirer@10.2.2: + resolution: {integrity: sha512-tyao/4Vo36XnUItZ7DnUXX4f1jVao2mSrleV/5IPtW/XAEA26hRVsbc68nuTEKWcr5vMP/1mVoT2O7u8H4v1Vg==} engines: {node: '>=18'} ipaddr.js@1.9.1: @@ -2146,15 +2196,15 @@ packages: pend@1.2.0: resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} - picocolors@1.1.0: - resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==} + picocolors@1.1.1: + resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==} picomatch@2.3.1: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} - postcss@8.4.47: - resolution: {integrity: sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==} + postcss@8.4.49: + resolution: {integrity: sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==} engines: {node: ^10 || ^12 || >=14} prebuild-install@7.1.2: @@ -2228,8 +2278,8 @@ packages: resolution: {integrity: sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==} hasBin: true - rollup@4.24.0: - resolution: {integrity: sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==} + rollup@4.27.3: + resolution: {integrity: sha512-SLsCOnlmGt9VoZ9Ek8yBK8tAdmPHeppkw+Xa7yDlCEhDTvwYei03JlWo1fdc7YTfLZ4tD8riJCUyAgTbszk1fQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} hasBin: true @@ -2407,8 +2457,8 @@ packages: tinyexec@0.3.1: resolution: {integrity: sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==} - tinypool@1.0.1: - resolution: {integrity: sha512-URZYihUbRPcGv95En+sz6MfghfIc2OJ1sv/RmhWZLouPY0/8Vo80viwPvg3dlaS9fuq7fQMEfgRRK7BBZThBEA==} + tinypool@1.0.2: + resolution: {integrity: sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==} engines: {node: ^18.0.0 || >=20.0.0} tinyrainbow@1.2.0: @@ -2441,6 +2491,9 @@ packages: tslib@2.8.0: resolution: {integrity: sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==} + tslib@2.8.1: + resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tunnel-agent@0.6.0: resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} @@ -2514,8 +2567,8 @@ packages: engines: {node: ^18.0.0 || >=20.0.0} hasBin: true - vite@5.4.8: - resolution: {integrity: sha512-FqrItQ4DT1NC4zCUqMB4c4AZORMKIa0m8/URVCZ77OZ/QSNeJ54bU1vrFADbDsuwfIPcgknRkmqakQcgnL4GiQ==} + vite@5.4.11: + resolution: {integrity: sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2767,20 +2820,20 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@emnapi/core@1.2.0': + '@emnapi/core@1.3.1': dependencies: '@emnapi/wasi-threads': 1.0.1 - tslib: 2.8.0 + tslib: 2.8.1 optional: true - '@emnapi/runtime@1.2.0': + '@emnapi/runtime@1.3.1': dependencies: - tslib: 2.8.0 + tslib: 2.8.1 optional: true '@emnapi/wasi-threads@1.0.1': dependencies: - tslib: 2.8.0 + tslib: 2.8.1 optional: true '@esbuild/aix-ppc64@0.21.5': @@ -2926,26 +2979,25 @@ snapshots: '@inquirer/checkbox@2.5.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 1.5.5 ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 '@inquirer/confirm@3.2.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 - '@inquirer/core@9.1.0': + '@inquirer/core@9.2.1': dependencies: - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 2.0.0 '@types/mute-stream': 0.0.4 - '@types/node': 22.9.0 + '@types/node': 22.9.1 '@types/wrap-ansi': 3.0.0 ansi-escapes: 4.3.2 - cli-spinners: 2.9.2 cli-width: 4.1.0 mute-stream: 1.0.0 signal-exit: 4.1.0 @@ -2955,40 +3007,40 @@ snapshots: '@inquirer/editor@2.2.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 external-editor: 3.1.0 - '@inquirer/expand@2.2.0': + '@inquirer/expand@2.3.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 yoctocolors-cjs: 2.1.2 - '@inquirer/figures@1.0.5': {} + '@inquirer/figures@1.0.8': {} '@inquirer/input@2.3.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 '@inquirer/number@1.1.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 '@inquirer/password@2.2.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 ansi-escapes: 4.3.2 - '@inquirer/prompts@5.4.0': + '@inquirer/prompts@5.5.0': dependencies: '@inquirer/checkbox': 2.5.0 '@inquirer/confirm': 3.2.0 '@inquirer/editor': 2.2.0 - '@inquirer/expand': 2.2.0 + '@inquirer/expand': 2.3.0 '@inquirer/input': 2.3.0 '@inquirer/number': 1.1.0 '@inquirer/password': 2.2.0 @@ -2998,26 +3050,30 @@ snapshots: '@inquirer/rawlist@2.3.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/type': 1.5.5 yoctocolors-cjs: 2.1.2 '@inquirer/search@1.1.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 1.5.5 yoctocolors-cjs: 2.1.2 '@inquirer/select@2.5.0': dependencies: - '@inquirer/core': 9.1.0 - '@inquirer/figures': 1.0.5 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/figures': 1.0.8 + '@inquirer/type': 1.5.5 ansi-escapes: 4.3.2 yoctocolors-cjs: 2.1.2 - '@inquirer/type@1.5.3': + '@inquirer/type@1.5.5': + dependencies: + mute-stream: 1.0.0 + + '@inquirer/type@2.0.0': dependencies: mute-stream: 1.0.0 @@ -3045,7 +3101,7 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 - '@napi-rs/cli@3.0.0-alpha.61(@emnapi/runtime@1.2.0)': + '@napi-rs/cli@3.0.0-alpha.61(@emnapi/runtime@1.3.1)': dependencies: '@napi-rs/cross-toolchain': 0.0.16 '@napi-rs/wasm-tools': 0.0.2 @@ -3053,7 +3109,7 @@ snapshots: clipanion: 3.2.1(typanion@3.14.0) colorette: 2.0.20 debug: 4.3.7(supports-color@8.1.1) - inquirer: 10.2.0 + inquirer: 10.2.2 js-yaml: 4.1.0 lodash-es: 4.17.21 semver: 7.6.3 @@ -3061,7 +3117,7 @@ snapshots: typanion: 3.14.0 wasm-sjlj: 1.0.5 optionalDependencies: - '@emnapi/runtime': 1.2.0 + '@emnapi/runtime': 1.3.1 transitivePeerDependencies: - '@napi-rs/cross-toolchain-arm64-target-aarch64' - '@napi-rs/cross-toolchain-arm64-target-armv7' @@ -3073,72 +3129,84 @@ snapshots: '@napi-rs/cross-toolchain@0.0.16': dependencies: - '@napi-rs/lzma': 1.3.1 + '@napi-rs/lzma': 1.4.1 '@napi-rs/tar': 0.1.4 debug: 4.3.7(supports-color@8.1.1) transitivePeerDependencies: - supports-color - '@napi-rs/lzma-android-arm-eabi@1.3.1': + '@napi-rs/lzma-android-arm-eabi@1.4.1': + optional: true + + '@napi-rs/lzma-android-arm64@1.4.1': optional: true - '@napi-rs/lzma-android-arm64@1.3.1': + '@napi-rs/lzma-darwin-arm64@1.4.1': optional: true - '@napi-rs/lzma-darwin-arm64@1.3.1': + '@napi-rs/lzma-darwin-x64@1.4.1': optional: true - '@napi-rs/lzma-darwin-x64@1.3.1': + '@napi-rs/lzma-freebsd-x64@1.4.1': optional: true - '@napi-rs/lzma-freebsd-x64@1.3.1': + '@napi-rs/lzma-linux-arm-gnueabihf@1.4.1': optional: true - '@napi-rs/lzma-linux-arm-gnueabihf@1.3.1': + '@napi-rs/lzma-linux-arm64-gnu@1.4.1': optional: true - '@napi-rs/lzma-linux-arm64-gnu@1.3.1': + '@napi-rs/lzma-linux-arm64-musl@1.4.1': optional: true - '@napi-rs/lzma-linux-arm64-musl@1.3.1': + '@napi-rs/lzma-linux-ppc64-gnu@1.4.1': optional: true - '@napi-rs/lzma-linux-x64-gnu@1.3.1': + '@napi-rs/lzma-linux-riscv64-gnu@1.4.1': optional: true - '@napi-rs/lzma-linux-x64-musl@1.3.1': + '@napi-rs/lzma-linux-s390x-gnu@1.4.1': optional: true - '@napi-rs/lzma-wasm32-wasi@1.3.1': + '@napi-rs/lzma-linux-x64-gnu@1.4.1': + optional: true + + '@napi-rs/lzma-linux-x64-musl@1.4.1': + optional: true + + '@napi-rs/lzma-wasm32-wasi@1.4.1': dependencies: - '@napi-rs/wasm-runtime': 0.2.4 + '@napi-rs/wasm-runtime': 0.2.5 optional: true - '@napi-rs/lzma-win32-arm64-msvc@1.3.1': + '@napi-rs/lzma-win32-arm64-msvc@1.4.1': optional: true - '@napi-rs/lzma-win32-ia32-msvc@1.3.1': + '@napi-rs/lzma-win32-ia32-msvc@1.4.1': optional: true - '@napi-rs/lzma-win32-x64-msvc@1.3.1': + '@napi-rs/lzma-win32-x64-msvc@1.4.1': optional: true - '@napi-rs/lzma@1.3.1': + '@napi-rs/lzma@1.4.1': optionalDependencies: - '@napi-rs/lzma-android-arm-eabi': 1.3.1 - '@napi-rs/lzma-android-arm64': 1.3.1 - '@napi-rs/lzma-darwin-arm64': 1.3.1 - '@napi-rs/lzma-darwin-x64': 1.3.1 - '@napi-rs/lzma-freebsd-x64': 1.3.1 - '@napi-rs/lzma-linux-arm-gnueabihf': 1.3.1 - '@napi-rs/lzma-linux-arm64-gnu': 1.3.1 - '@napi-rs/lzma-linux-arm64-musl': 1.3.1 - '@napi-rs/lzma-linux-x64-gnu': 1.3.1 - '@napi-rs/lzma-linux-x64-musl': 1.3.1 - '@napi-rs/lzma-wasm32-wasi': 1.3.1 - '@napi-rs/lzma-win32-arm64-msvc': 1.3.1 - '@napi-rs/lzma-win32-ia32-msvc': 1.3.1 - '@napi-rs/lzma-win32-x64-msvc': 1.3.1 + '@napi-rs/lzma-android-arm-eabi': 1.4.1 + '@napi-rs/lzma-android-arm64': 1.4.1 + '@napi-rs/lzma-darwin-arm64': 1.4.1 + '@napi-rs/lzma-darwin-x64': 1.4.1 + '@napi-rs/lzma-freebsd-x64': 1.4.1 + '@napi-rs/lzma-linux-arm-gnueabihf': 1.4.1 + '@napi-rs/lzma-linux-arm64-gnu': 1.4.1 + '@napi-rs/lzma-linux-arm64-musl': 1.4.1 + '@napi-rs/lzma-linux-ppc64-gnu': 1.4.1 + '@napi-rs/lzma-linux-riscv64-gnu': 1.4.1 + '@napi-rs/lzma-linux-s390x-gnu': 1.4.1 + '@napi-rs/lzma-linux-x64-gnu': 1.4.1 + '@napi-rs/lzma-linux-x64-musl': 1.4.1 + '@napi-rs/lzma-wasm32-wasi': 1.4.1 + '@napi-rs/lzma-win32-arm64-msvc': 1.4.1 + '@napi-rs/lzma-win32-ia32-msvc': 1.4.1 + '@napi-rs/lzma-win32-x64-msvc': 1.4.1 '@napi-rs/tar-android-arm-eabi@0.1.4': optional: true @@ -3178,7 +3246,7 @@ snapshots: '@napi-rs/tar-wasm32-wasi@0.1.4': dependencies: - '@napi-rs/wasm-runtime': 0.2.4 + '@napi-rs/wasm-runtime': 0.2.5 optional: true '@napi-rs/tar-win32-arm64-msvc@0.1.4': @@ -3209,10 +3277,10 @@ snapshots: '@napi-rs/tar-win32-ia32-msvc': 0.1.4 '@napi-rs/tar-win32-x64-msvc': 0.1.4 - '@napi-rs/wasm-runtime@0.2.4': + '@napi-rs/wasm-runtime@0.2.5': dependencies: - '@emnapi/core': 1.2.0 - '@emnapi/runtime': 1.2.0 + '@emnapi/core': 1.3.1 + '@emnapi/runtime': 1.3.1 '@tybys/wasm-util': 0.9.0 optional: true @@ -3245,7 +3313,7 @@ snapshots: '@napi-rs/wasm-tools-wasm32-wasi@0.0.2': dependencies: - '@napi-rs/wasm-runtime': 0.2.4 + '@napi-rs/wasm-runtime': 0.2.5 optional: true '@napi-rs/wasm-tools-win32-arm64-msvc@0.0.2': @@ -3280,57 +3348,57 @@ snapshots: '@octokit/auth-token': 5.1.1 '@octokit/graphql': 8.1.1 '@octokit/request': 9.1.3 - '@octokit/request-error': 6.1.4 - '@octokit/types': 13.5.0 + '@octokit/request-error': 6.1.5 + '@octokit/types': 13.6.1 before-after-hook: 3.0.2 universal-user-agent: 7.0.2 '@octokit/endpoint@10.1.1': dependencies: - '@octokit/types': 13.5.0 + '@octokit/types': 13.6.1 universal-user-agent: 7.0.2 '@octokit/graphql@8.1.1': dependencies: '@octokit/request': 9.1.3 - '@octokit/types': 13.5.0 + '@octokit/types': 13.6.1 universal-user-agent: 7.0.2 '@octokit/openapi-types@22.2.0': {} - '@octokit/plugin-paginate-rest@11.3.3(@octokit/core@6.1.2)': + '@octokit/plugin-paginate-rest@11.3.5(@octokit/core@6.1.2)': dependencies: '@octokit/core': 6.1.2 - '@octokit/types': 13.5.0 + '@octokit/types': 13.6.1 '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.2)': dependencies: '@octokit/core': 6.1.2 - '@octokit/plugin-rest-endpoint-methods@13.2.4(@octokit/core@6.1.2)': + '@octokit/plugin-rest-endpoint-methods@13.2.6(@octokit/core@6.1.2)': dependencies: '@octokit/core': 6.1.2 - '@octokit/types': 13.5.0 + '@octokit/types': 13.6.1 - '@octokit/request-error@6.1.4': + '@octokit/request-error@6.1.5': dependencies: - '@octokit/types': 13.5.0 + '@octokit/types': 13.6.1 '@octokit/request@9.1.3': dependencies: '@octokit/endpoint': 10.1.1 - '@octokit/request-error': 6.1.4 - '@octokit/types': 13.5.0 + '@octokit/request-error': 6.1.5 + '@octokit/types': 13.6.1 universal-user-agent: 7.0.2 '@octokit/rest@21.0.2': dependencies: '@octokit/core': 6.1.2 - '@octokit/plugin-paginate-rest': 11.3.3(@octokit/core@6.1.2) + '@octokit/plugin-paginate-rest': 11.3.5(@octokit/core@6.1.2) '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.2) - '@octokit/plugin-rest-endpoint-methods': 13.2.4(@octokit/core@6.1.2) + '@octokit/plugin-rest-endpoint-methods': 13.2.6(@octokit/core@6.1.2) - '@octokit/types@13.5.0': + '@octokit/types@13.6.1': dependencies: '@octokit/openapi-types': 22.2.0 @@ -3361,57 +3429,63 @@ snapshots: '@pkgjs/parseargs@0.11.0': optional: true - '@rollup/rollup-android-arm-eabi@4.24.0': + '@rollup/rollup-android-arm-eabi@4.27.3': + optional: true + + '@rollup/rollup-android-arm64@4.27.3': optional: true - '@rollup/rollup-android-arm64@4.24.0': + '@rollup/rollup-darwin-arm64@4.27.3': optional: true - '@rollup/rollup-darwin-arm64@4.24.0': + '@rollup/rollup-darwin-x64@4.27.3': optional: true - '@rollup/rollup-darwin-x64@4.24.0': + '@rollup/rollup-freebsd-arm64@4.27.3': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.24.0': + '@rollup/rollup-freebsd-x64@4.27.3': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.24.0': + '@rollup/rollup-linux-arm-gnueabihf@4.27.3': optional: true - '@rollup/rollup-linux-arm64-gnu@4.24.0': + '@rollup/rollup-linux-arm-musleabihf@4.27.3': optional: true - '@rollup/rollup-linux-arm64-musl@4.24.0': + '@rollup/rollup-linux-arm64-gnu@4.27.3': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.24.0': + '@rollup/rollup-linux-arm64-musl@4.27.3': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.24.0': + '@rollup/rollup-linux-powerpc64le-gnu@4.27.3': optional: true - '@rollup/rollup-linux-s390x-gnu@4.24.0': + '@rollup/rollup-linux-riscv64-gnu@4.27.3': optional: true - '@rollup/rollup-linux-x64-gnu@4.24.0': + '@rollup/rollup-linux-s390x-gnu@4.27.3': optional: true - '@rollup/rollup-linux-x64-musl@4.24.0': + '@rollup/rollup-linux-x64-gnu@4.27.3': optional: true - '@rollup/rollup-win32-arm64-msvc@4.24.0': + '@rollup/rollup-linux-x64-musl@4.27.3': optional: true - '@rollup/rollup-win32-ia32-msvc@4.24.0': + '@rollup/rollup-win32-arm64-msvc@4.27.3': optional: true - '@rollup/rollup-win32-x64-msvc@4.24.0': + '@rollup/rollup-win32-ia32-msvc@4.27.3': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.27.3': optional: true '@tybys/wasm-util@0.9.0': dependencies: - tslib: 2.8.0 + tslib: 2.8.1 optional: true '@types/estree@1.0.6': {} @@ -3422,9 +3496,9 @@ snapshots: '@types/mute-stream@0.0.4': dependencies: - '@types/node': 22.9.0 + '@types/node': 22.9.1 - '@types/node@22.9.0': + '@types/node@22.9.1': dependencies: undici-types: 6.19.8 @@ -3439,13 +3513,13 @@ snapshots: chai: 5.1.2 tinyrainbow: 1.2.0 - '@vitest/mocker@2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.9.0))': + '@vitest/mocker@2.1.2(@vitest/spy@2.1.2)(vite@5.4.11(@types/node@22.9.1))': dependencies: '@vitest/spy': 2.1.2 estree-walker: 3.0.3 magic-string: 0.30.13 optionalDependencies: - vite: 5.4.8(@types/node@22.9.0) + vite: 5.4.11(@types/node@22.9.1) '@vitest/pretty-format@2.1.2': dependencies: @@ -4275,10 +4349,11 @@ snapshots: ini@1.3.8: optional: true - inquirer@10.2.0: + inquirer@10.2.2: dependencies: - '@inquirer/prompts': 5.4.0 - '@inquirer/type': 1.5.3 + '@inquirer/core': 9.2.1 + '@inquirer/prompts': 5.5.0 + '@inquirer/type': 1.5.5 '@types/mute-stream': 0.0.4 ansi-escapes: 4.3.2 mute-stream: 1.0.0 @@ -4685,14 +4760,14 @@ snapshots: pend@1.2.0: {} - picocolors@1.1.0: {} + picocolors@1.1.1: {} picomatch@2.3.1: {} - postcss@8.4.47: + postcss@8.4.49: dependencies: nanoid: 3.3.7 - picocolors: 1.1.0 + picocolors: 1.1.1 source-map-js: 1.2.1 prebuild-install@7.1.2: @@ -4790,33 +4865,35 @@ snapshots: dependencies: glob: 10.4.5 - rollup@4.24.0: + rollup@4.27.3: dependencies: '@types/estree': 1.0.6 optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.24.0 - '@rollup/rollup-android-arm64': 4.24.0 - '@rollup/rollup-darwin-arm64': 4.24.0 - '@rollup/rollup-darwin-x64': 4.24.0 - '@rollup/rollup-linux-arm-gnueabihf': 4.24.0 - '@rollup/rollup-linux-arm-musleabihf': 4.24.0 - '@rollup/rollup-linux-arm64-gnu': 4.24.0 - '@rollup/rollup-linux-arm64-musl': 4.24.0 - '@rollup/rollup-linux-powerpc64le-gnu': 4.24.0 - '@rollup/rollup-linux-riscv64-gnu': 4.24.0 - '@rollup/rollup-linux-s390x-gnu': 4.24.0 - '@rollup/rollup-linux-x64-gnu': 4.24.0 - '@rollup/rollup-linux-x64-musl': 4.24.0 - '@rollup/rollup-win32-arm64-msvc': 4.24.0 - '@rollup/rollup-win32-ia32-msvc': 4.24.0 - '@rollup/rollup-win32-x64-msvc': 4.24.0 + '@rollup/rollup-android-arm-eabi': 4.27.3 + '@rollup/rollup-android-arm64': 4.27.3 + '@rollup/rollup-darwin-arm64': 4.27.3 + '@rollup/rollup-darwin-x64': 4.27.3 + '@rollup/rollup-freebsd-arm64': 4.27.3 + '@rollup/rollup-freebsd-x64': 4.27.3 + '@rollup/rollup-linux-arm-gnueabihf': 4.27.3 + '@rollup/rollup-linux-arm-musleabihf': 4.27.3 + '@rollup/rollup-linux-arm64-gnu': 4.27.3 + '@rollup/rollup-linux-arm64-musl': 4.27.3 + '@rollup/rollup-linux-powerpc64le-gnu': 4.27.3 + '@rollup/rollup-linux-riscv64-gnu': 4.27.3 + '@rollup/rollup-linux-s390x-gnu': 4.27.3 + '@rollup/rollup-linux-x64-gnu': 4.27.3 + '@rollup/rollup-linux-x64-musl': 4.27.3 + '@rollup/rollup-win32-arm64-msvc': 4.27.3 + '@rollup/rollup-win32-ia32-msvc': 4.27.3 + '@rollup/rollup-win32-x64-msvc': 4.27.3 fsevents: 2.3.3 run-async@3.0.0: {} rxjs@7.8.1: dependencies: - tslib: 2.8.0 + tslib: 2.8.1 safe-buffer@5.1.2: {} @@ -5008,7 +5085,7 @@ snapshots: tinyexec@0.3.1: {} - tinypool@1.0.1: {} + tinypool@1.0.2: {} tinyrainbow@1.2.0: {} @@ -5030,6 +5107,8 @@ snapshots: tslib@2.8.0: {} + tslib@2.8.1: {} + tunnel-agent@0.6.0: dependencies: safe-buffer: 5.2.1 @@ -5082,12 +5161,12 @@ snapshots: vary@1.1.2: {} - vite-node@2.1.2(@types/node@22.9.0): + vite-node@2.1.2(@types/node@22.9.1): dependencies: cac: 6.7.14 debug: 4.3.7(supports-color@8.1.1) pathe: 1.1.2 - vite: 5.4.8(@types/node@22.9.0) + vite: 5.4.11(@types/node@22.9.1) transitivePeerDependencies: - '@types/node' - less @@ -5099,19 +5178,19 @@ snapshots: - supports-color - terser - vite@5.4.8(@types/node@22.9.0): + vite@5.4.11(@types/node@22.9.1): dependencies: esbuild: 0.21.5 - postcss: 8.4.47 - rollup: 4.24.0 + postcss: 8.4.49 + rollup: 4.27.3 optionalDependencies: - '@types/node': 22.9.0 + '@types/node': 22.9.1 fsevents: 2.3.3 - vitest@2.1.2(@types/node@22.9.0): + vitest@2.1.2(@types/node@22.9.1): dependencies: '@vitest/expect': 2.1.2 - '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.8(@types/node@22.9.0)) + '@vitest/mocker': 2.1.2(@vitest/spy@2.1.2)(vite@5.4.11(@types/node@22.9.1)) '@vitest/pretty-format': 2.1.5 '@vitest/runner': 2.1.2 '@vitest/snapshot': 2.1.2 @@ -5124,13 +5203,13 @@ snapshots: std-env: 3.8.0 tinybench: 2.9.0 tinyexec: 0.3.1 - tinypool: 1.0.1 + tinypool: 1.0.2 tinyrainbow: 1.2.0 - vite: 5.4.8(@types/node@22.9.0) - vite-node: 2.1.2(@types/node@22.9.0) + vite: 5.4.11(@types/node@22.9.1) + vite-node: 2.1.2(@types/node@22.9.1) why-is-node-running: 2.3.0 optionalDependencies: - '@types/node': 22.9.0 + '@types/node': 22.9.1 transitivePeerDependencies: - less - lightningcss diff --git a/tasks/transform_conformance/snapshots/babel_exec.snap.md b/tasks/transform_conformance/snapshots/babel_exec.snap.md index b38b07fced5656..84039ef7f342ab 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -5,11 +5,11 @@ node: v22.11.0 FAIL fixtures/babel-plugin-transform-arrow-functions-test-fixtures-arrow-functions-implicit-var-arguments-exec.test.js [ fixtures/babel-plugin-transform-arrow-functions-test-fixtures-arrow-functions-implicit-var-arguments-exec.test.js ] Error: 'eval' and 'arguments' cannot be used as a binding identifier in strict mode - ❯ getRollupError ../../node_modules/.pnpm/rollup@4.24.0/node_modules/rollup/dist/es/shared/parseAst.js:395:41 - ❯ convertProgram ../../node_modules/.pnpm/rollup@4.24.0/node_modules/rollup/dist/es/shared/parseAst.js:1083:26 - ❯ parseAstAsync ../../node_modules/.pnpm/rollup@4.24.0/node_modules/rollup/dist/es/shared/parseAst.js:2069:106 - ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52319:11 - ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.9.0/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:51917:72 + ❯ getRollupError ../../node_modules/.pnpm/rollup@4.27.3/node_modules/rollup/dist/es/shared/parseAst.js:396:41 + ❯ convertProgram ../../node_modules/.pnpm/rollup@4.27.3/node_modules/rollup/dist/es/shared/parseAst.js:1084:26 + ❯ parseAstAsync ../../node_modules/.pnpm/rollup@4.27.3/node_modules/rollup/dist/es/shared/parseAst.js:2070:106 + ❯ ssrTransformScript ../../node_modules/.pnpm/vite@5.4.11_@types+node@22.9.1/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:52381:11 + ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.11_@types+node@22.9.1/node_modules/vite/dist/node/chunks/dep-CB_7IfJ-.js:51979:72 ⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/4]⎯ From 6a98ef1a0c4e68251078483f57d17ecaebd9c34e Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Wed, 20 Nov 2024 09:27:29 +0000 Subject: [PATCH 056/121] feat(transformer): add `CompilerAssumptions` to `TransformContext` (#7369) --- crates/oxc_transformer/src/context.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/crates/oxc_transformer/src/context.rs b/crates/oxc_transformer/src/context.rs index 12963d856dc1fb..693cff88cd070a 100644 --- a/crates/oxc_transformer/src/context.rs +++ b/crates/oxc_transformer/src/context.rs @@ -13,7 +13,7 @@ use crate::{ statement_injector::StatementInjectorStore, top_level_statements::TopLevelStatementsStore, var_declarations::VarDeclarationsStore, }, - Module, TransformOptions, + CompilerAssumptions, Module, TransformOptions, }; pub struct TransformCtx<'a> { @@ -31,6 +31,9 @@ pub struct TransformCtx<'a> { pub module: Module, + #[expect(dead_code)] + pub assumptions: CompilerAssumptions, + // Helpers /// Manage helper loading pub helper_loader: HelperLoaderStore<'a>, @@ -61,6 +64,7 @@ impl<'a> TransformCtx<'a> { source_type: SourceType::default(), source_text: "", module: options.env.module, + assumptions: options.assumptions, helper_loader: HelperLoaderStore::new(&options.helper_loader), module_imports: ModuleImportsStore::new(), var_declarations: VarDeclarationsStore::new(), From 7bf970a4b6efbb099ac4a79982a5eff60acdeaf9 Mon Sep 17 00:00:00 2001 From: Boshen <1430279+Boshen@users.noreply.github.com> Date: Wed, 20 Nov 2024 11:46:29 +0000 Subject: [PATCH 057/121] refactor(linter)!: remove tree_shaking plugin (#7372) This rule has been in `nursery` for a long time and I don't see it coming out of `nursery` in the foreseeable future. closes #7031 clsoes #7057 --- crates/oxc_linter/src/context/mod.rs | 1 - crates/oxc_linter/src/rules.rs | 5 - .../listener_map.rs | 1354 ----------------- .../no_side_effects_in_initialization/mod.rs | 896 ----------- .../adjacent_overload_signatures.snap | 1 + crates/oxc_linter/src/snapshots/alt_text.snap | 1 + .../src/snapshots/anchor_has_content.snap | 1 + .../src/snapshots/anchor_is_valid.snap | 1 + .../snapshots/api_keys@aws_access_token.snap | 1 + .../src/snapshots/approx_constant.snap | 1 + .../aria_activedescendant_has_tabindex.snap | 1 + .../oxc_linter/src/snapshots/aria_props.snap | 1 + .../oxc_linter/src/snapshots/aria_role.snap | 1 + .../snapshots/aria_unsupported_elements.snap | 1 + .../src/snapshots/array_callback_return.snap | 1 + .../oxc_linter/src/snapshots/array_type.snap | 1 + .../src/snapshots/autocomplete_valid.snap | 1 + .../oxc_linter/src/snapshots/avoid_new.snap | 1 + .../bad_array_method_on_arguments.snap | 1 + .../src/snapshots/bad_bitwise_operator.snap | 1 + .../src/snapshots/bad_char_at_comparison.snap | 1 + .../snapshots/bad_comparison_sequence.snap | 1 + .../src/snapshots/bad_min_max_func.snap | 1 + .../bad_object_literal_comparison.snap | 1 + .../src/snapshots/bad_replace_all_arg.snap | 1 + .../src/snapshots/ban_ts_comment.snap | 1 + .../src/snapshots/ban_tslint_comment.snap | 1 + .../oxc_linter/src/snapshots/ban_types.snap | 1 + .../src/snapshots/button_has_type.snap | 1 + .../src/snapshots/catch_error_name.snap | 1 + .../src/snapshots/catch_or_return.snap | 1 + .../src/snapshots/check_access.snap | 1 + .../src/snapshots/check_property_names.snap | 1 + .../src/snapshots/check_tag_names.snap | 1 + ...checked_requires_onchange_or_readonly.snap | 1 + .../click_events_have_key_events.snap | 1 + .../consistent_empty_array_spread.snap | 1 + .../consistent_function_scoping.snap | 1 + .../consistent_indexed_object_style.snap | 1 + .../src/snapshots/consistent_test_it.snap | 1 + .../consistent_type_definitions.snap | 1 + .../snapshots/consistent_type_imports.snap | 1 + .../src/snapshots/const_comparisons.snap | 1 + .../src/snapshots/constructor_super.snap | 1 + crates/oxc_linter/src/snapshots/default.snap | 1 + .../src/snapshots/default_case.snap | 1 + .../src/snapshots/default_case_last.snap | 1 + .../src/snapshots/default_param_last.snap | 1 + .../src/snapshots/double_comparisons.snap | 1 + .../src/snapshots/empty_brace_spaces.snap | 1 + .../oxc_linter/src/snapshots/empty_tags.snap | 1 + crates/oxc_linter/src/snapshots/eqeqeq.snap | 1 + .../oxc_linter/src/snapshots/erasing_op.snap | 1 + .../src/snapshots/error_message.snap | 1 + .../oxc_linter/src/snapshots/escape_case.snap | 1 + .../src/snapshots/exhaustive_deps.snap | 1 + .../src/snapshots/expect_expect.snap | 1 + .../explicit_function_return_type.snap | 1 + .../src/snapshots/explicit_length_check.snap | 1 + crates/oxc_linter/src/snapshots/export.snap | 1 + .../src/snapshots/filename_case.snap | 1 + crates/oxc_linter/src/snapshots/first.snap | 1 + .../src/snapshots/for_direction.snap | 1 + .../oxc_linter/src/snapshots/func_names.snap | 1 + .../src/snapshots/getter_return.snap | 1 + .../src/snapshots/google_font_display.snap | 1 + .../src/snapshots/google_font_preconnect.snap | 1 + .../src/snapshots/guard_for_in.snap | 1 + .../src/snapshots/heading_has_content.snap | 1 + .../src/snapshots/html_has_lang.snap | 1 + .../src/snapshots/iframe_has_title.snap | 1 + .../src/snapshots/iframe_missing_sandbox.snap | 1 + .../src/snapshots/img_redundant_alt.snap | 1 + .../src/snapshots/implements_on_classes.snap | 1 + .../src/snapshots/import_no_namespace.snap | 1 + .../src/snapshots/inline_script_id.snap | 1 + .../src/snapshots/jsx_boolean_value.snap | 1 + .../snapshots/jsx_curly_brace_presence.snap | 1 + crates/oxc_linter/src/snapshots/jsx_key.snap | 1 + .../snapshots/jsx_no_comment_textnodes.snap | 1 + .../src/snapshots/jsx_no_duplicate_props.snap | 1 + .../src/snapshots/jsx_no_jsx_as_prop.snap | 1 + .../snapshots/jsx_no_new_array_as_prop.snap | 1 + .../jsx_no_new_function_as_prop.snap | 1 + .../snapshots/jsx_no_new_object_as_prop.snap | 1 + .../src/snapshots/jsx_no_target_blank.snap | 1 + .../src/snapshots/jsx_no_undef.snap | 1 + .../snapshots/jsx_no_useless_fragment.snap | 1 + .../snapshots/jsx_props_no_spread_multi.snap | 1 + .../label_has_associated_control.snap | 1 + crates/oxc_linter/src/snapshots/lang.snap | 1 + .../src/snapshots/max_classes_per_file.snap | 1 + .../src/snapshots/max_dependencies.snap | 1 + .../oxc_linter/src/snapshots/max_expects.snap | 1 + .../oxc_linter/src/snapshots/max_lines.snap | 1 + .../src/snapshots/max_nested_describe.snap | 1 + .../oxc_linter/src/snapshots/max_params.snap | 1 + .../src/snapshots/media_has_caption.snap | 1 + .../snapshots/misrefactored_assign_op.snap | 1 + .../src/snapshots/missing_throw.snap | 1 + .../mouse_events_have_key_events.snap | 1 + crates/oxc_linter/src/snapshots/named.snap | 1 + .../oxc_linter/src/snapshots/namespace.snap | 1 + .../src/snapshots/new_for_builtins.snap | 1 + .../src/snapshots/next_script_for_ga.snap | 1 + .../snapshots/no_abusive_eslint_disable.snap | 1 + .../src/snapshots/no_access_key.snap | 1 + .../src/snapshots/no_accumulating_spread.snap | 1 + crates/oxc_linter/src/snapshots/no_alert.snap | 1 + .../src/snapshots/no_alias_methods.snap | 1 + crates/oxc_linter/src/snapshots/no_amd.snap | 1 + .../no_anonymous_default_export.snap | 1 + .../no_aria_hidden_on_focusable.snap | 1 + .../src/snapshots/no_array_constructor.snap | 1 + .../src/snapshots/no_array_for_each.snap | 1 + .../src/snapshots/no_array_reduce.snap | 1 + .../snapshots/no_assign_module_variable.snap | 1 + .../src/snapshots/no_async_await.snap | 1 + .../snapshots/no_async_client_component.snap | 1 + .../snapshots/no_async_endpoint_handlers.snap | 1 + .../snapshots/no_async_promise_executor.snap | 1 + .../src/snapshots/no_autofocus.snap | 1 + .../snapshots/no_await_expression_member.snap | 1 + .../src/snapshots/no_await_in_loop.snap | 1 + .../no_await_in_promise_methods.snap | 1 + .../src/snapshots/no_barrel_file.snap | 1 + ...e_interactive_script_outside_document.snap | 1 + .../oxc_linter/src/snapshots/no_bitwise.snap | 1 + .../src/snapshots/no_callback_in_promise.snap | 1 + .../oxc_linter/src/snapshots/no_caller.snap | 1 + .../src/snapshots/no_case_declarations.snap | 1 + .../src/snapshots/no_children_prop.snap | 1 + .../src/snapshots/no_class_assign.snap | 1 + .../src/snapshots/no_commented_out_tests.snap | 2 +- .../oxc_linter/src/snapshots/no_commonjs.snap | 1 + .../src/snapshots/no_compare_neg_zero.snap | 1 + .../src/snapshots/no_cond_assign.snap | 1 + .../src/snapshots/no_conditional_expect.snap | 1 + .../src/snapshots/no_conditional_in_test.snap | 1 + .../src/snapshots/no_conditional_tests.snap | 1 + .../no_confusing_non_null_assertion.snap | 1 + .../snapshots/no_confusing_set_timeout.snap | 1 + .../oxc_linter/src/snapshots/no_console.snap | 1 + .../src/snapshots/no_console_spaces.snap | 1 + .../src/snapshots/no_const_assign.snap | 1 + .../src/snapshots/no_const_enum.snap | 1 + .../no_constant_binary_expression.snap | 1 + .../src/snapshots/no_constant_condition.snap | 1 + .../src/snapshots/no_constructor_return.snap | 1 + .../oxc_linter/src/snapshots/no_continue.snap | 1 + .../src/snapshots/no_control_regex.snap | Bin 3941 -> 3961 bytes ..._control_regex@capture-group-indexing.snap | 1 + .../oxc_linter/src/snapshots/no_css_tags.snap | 1 + crates/oxc_linter/src/snapshots/no_cycle.snap | 1 + .../oxc_linter/src/snapshots/no_danger.snap | 1 + .../snapshots/no_danger_with_children.snap | 1 + .../oxc_linter/src/snapshots/no_debugger.snap | 1 + .../src/snapshots/no_default_export.snap | 1 + .../oxc_linter/src/snapshots/no_defaults.snap | 1 + .../src/snapshots/no_delete_var.snap | 1 + .../snapshots/no_deprecated_functions.snap | 1 + .../snapshots/no_direct_mutation_state.snap | 1 + .../src/snapshots/no_disabled_tests.snap | 1 + .../snapshots/no_distracting_elements.snap | 1 + .../src/snapshots/no_div_regex.snap | 1 + .../src/snapshots/no_document_cookie.snap | 1 + .../snapshots/no_document_import_in_page.snap | 1 + .../src/snapshots/no_done_callback.snap | 1 + .../src/snapshots/no_dupe_class_members.snap | 1 + .../src/snapshots/no_dupe_else_if.snap | 1 + .../src/snapshots/no_dupe_keys.snap | 1 + .../src/snapshots/no_duplicate_case.snap | 1 + .../snapshots/no_duplicate_enum_values.snap | 1 + .../src/snapshots/no_duplicate_head.snap | 1 + .../src/snapshots/no_duplicate_hooks.snap | 1 + .../src/snapshots/no_duplicates.snap | 1 + .../src/snapshots/no_dynamic_delete.snap | 1 + .../src/snapshots/no_dynamic_require.snap | 1 + .../src/snapshots/no_else_return.snap | 1 + crates/oxc_linter/src/snapshots/no_empty.snap | 1 + .../snapshots/no_empty_character_class.snap | 1 + .../src/snapshots/no_empty_file.snap | 1 + .../src/snapshots/no_empty_function.snap | 1 + .../src/snapshots/no_empty_interface.snap | 1 + .../src/snapshots/no_empty_object_type.snap | 1 + .../src/snapshots/no_empty_pattern.snap | 1 + .../src/snapshots/no_empty_static_block.snap | 1 + .../oxc_linter/src/snapshots/no_eq_null.snap | 1 + crates/oxc_linter/src/snapshots/no_eval.snap | 1 + .../src/snapshots/no_ex_assign.snap | 1 + .../src/snapshots/no_explicit_any.snap | 1 + .../oxc_linter/src/snapshots/no_export.snap | 1 + .../src/snapshots/no_exports_assign.snap | 1 + .../src/snapshots/no_extend_native.snap | 1 + .../src/snapshots/no_extra_boolean_cast.snap | 1 + .../no_extra_non_null_assertion.snap | 1 + .../src/snapshots/no_extraneous_class.snap | 1 + .../src/snapshots/no_fallthrough.snap | 1 + .../src/snapshots/no_find_dom_node.snap | 1 + .../src/snapshots/no_focused_tests.snap | 1 + .../src/snapshots/no_func_assign.snap | 1 + .../src/snapshots/no_global_assign.snap | 1 + .../src/snapshots/no_head_element.snap | 1 + .../snapshots/no_head_import_in_document.snap | 1 + .../src/snapshots/no_hex_escape.snap | 1 + crates/oxc_linter/src/snapshots/no_hooks.snap | 1 + .../src/snapshots/no_identical_title.snap | 2 +- .../src/snapshots/no_img_element.snap | 1 + .../src/snapshots/no_import_assign.snap | 1 + .../src/snapshots/no_import_node_test.snap | 1 + .../no_import_type_side_effects.snap | 1 + .../src/snapshots/no_inner_declarations.snap | 1 + .../src/snapshots/no_instanceof_array.snap | 1 + .../no_interpolation_in_snapshots.snap | 1 + .../src/snapshots/no_invalid_regexp.snap | 1 + .../no_invalid_remove_event_listener.snap | 1 + .../snapshots/no_irregular_whitespace.snap | 1 + .../src/snapshots/no_is_mounted.snap | 1 + .../oxc_linter/src/snapshots/no_iterator.snap | 1 + .../src/snapshots/no_jasmine_globals.snap | 1 + .../src/snapshots/no_label_var.snap | 1 + .../src/snapshots/no_large_snapshots.snap | 1 + .../src/snapshots/no_length_as_slice_end.snap | 1 + .../src/snapshots/no_lonely_if.snap | 1 + .../src/snapshots/no_loss_of_precision.snap | 1 + .../snapshots/no_magic_array_flat_depth.snap | 1 + .../src/snapshots/no_magic_numbers.snap | 1 + .../src/snapshots/no_map_spread.snap | 1 + .../src/snapshots/no_misused_new.snap | 1 + .../src/snapshots/no_mocks_import.snap | 1 + .../src/snapshots/no_multi_str.snap | 1 + .../src/snapshots/no_named_as_default.snap | 1 + .../snapshots/no_named_as_default_member.snap | 1 + .../src/snapshots/no_namespace.snap | 1 + .../src/snapshots/no_negated_condition.snap | 1 + .../no_negation_in_equality_check.snap | 1 + .../src/snapshots/no_nested_ternary.snap | 1 + crates/oxc_linter/src/snapshots/no_new.snap | 1 + .../src/snapshots/no_new_array.snap | 1 + .../src/snapshots/no_new_buffer.snap | 1 + .../oxc_linter/src/snapshots/no_new_func.snap | 1 + .../no_new_native_nonconstructor.snap | 1 + .../src/snapshots/no_new_require.snap | 1 + .../src/snapshots/no_new_statics.snap | 1 + .../src/snapshots/no_new_wrappers.snap | 1 + ..._non_null_asserted_nullish_coalescing.snap | 1 + .../no_non_null_asserted_optional_chain.snap | 1 + .../src/snapshots/no_non_null_assertion.snap | 1 + .../snapshots/no_nonoctal_decimal_escape.snap | 1 + crates/oxc_linter/src/snapshots/no_null.snap | 1 + .../src/snapshots/no_obj_calls.snap | 1 + .../no_object_as_default_parameter.snap | 1 + .../src/snapshots/no_optional_chaining.snap | 1 + .../src/snapshots/no_page_custom_font.snap | 1 + .../oxc_linter/src/snapshots/no_plusplus.snap | 1 + .../src/snapshots/no_process_exit.snap | 1 + crates/oxc_linter/src/snapshots/no_proto.snap | 1 + .../src/snapshots/no_prototype_builtins.snap | 1 + .../src/snapshots/no_redeclare.snap | 1 + .../src/snapshots/no_redundant_roles.snap | 1 + .../src/snapshots/no_regex_spaces.snap | 1 + .../src/snapshots/no_render_return_value.snap | 1 + .../snapshots/no_rest_spread_properties.snap | 1 + .../src/snapshots/no_restricted_globals.snap | 1 + .../snapshots/no_restricted_jest_methods.snap | 1 + .../src/snapshots/no_restricted_matchers.snap | 1 + .../src/snapshots/no_return_assign.snap | 1 + .../src/snapshots/no_return_in_finally.snap | 1 + .../no_script_component_in_head.snap | 1 + .../src/snapshots/no_script_url.snap | 1 + .../src/snapshots/no_self_assign.snap | 1 + .../src/snapshots/no_self_compare.snap | 1 + .../src/snapshots/no_set_state.snap | 1 + .../src/snapshots/no_setter_return.snap | 1 + .../snapshots/no_shadow_restricted_names.snap | 1 + .../no_side_effects_in_initialization.snap | 1302 ---------------- .../no_single_promise_in_promise_methods.snap | 1 + .../src/snapshots/no_sparse_arrays.snap | 1 + .../src/snapshots/no_standalone_expect.snap | 1 + .../src/snapshots/no_static_only_class.snap | 1 + .../src/snapshots/no_string_refs.snap | 1 + .../snapshots/no_styled_jsx_in_document.snap | 1 + .../src/snapshots/no_sync_scripts.snap | 1 + .../no_template_curly_in_string.snap | 1 + .../oxc_linter/src/snapshots/no_ternary.snap | 1 + .../src/snapshots/no_test_prefixes.snap | 1 + .../snapshots/no_test_return_statement.snap | 1 + .../oxc_linter/src/snapshots/no_thenable.snap | 1 + .../src/snapshots/no_this_alias.snap | 1 + .../src/snapshots/no_this_assignment.snap | 1 + .../src/snapshots/no_this_before_super.snap | 1 + .../src/snapshots/no_throw_literal.snap | 1 + .../snapshots/no_title_in_document_head.snap | 1 + .../src/snapshots/no_typeof_undefined.snap | 1 + crates/oxc_linter/src/snapshots/no_typos.snap | 1 + crates/oxc_linter/src/snapshots/no_undef.snap | 1 + .../src/snapshots/no_undefined.snap | 1 + .../src/snapshots/no_unescaped_entities.snap | 1 + .../snapshots/no_unexpected_multiline.snap | 1 + .../src/snapshots/no_unknown_property.snap | 1 + .../src/snapshots/no_unnecessary_await.snap | 1 + .../no_unnecessary_type_constraint.snap | 1 + .../src/snapshots/no_unreachable.snap | 1 + .../no_unreadable_array_destructuring.snap | 1 + .../src/snapshots/no_unreadable_iife.snap | 1 + .../no_unsafe_declaration_merging.snap | 1 + .../src/snapshots/no_unsafe_finally.snap | 1 + .../snapshots/no_unsafe_function_type.snap | 1 + .../src/snapshots/no_unsafe_negation.snap | 1 + .../no_unsafe_optional_chaining.snap | 1 + .../snapshots/no_untyped_mock_factory.snap | 1 + .../src/snapshots/no_unused_labels.snap | 1 + .../no_unused_private_class_members.snap | 1 + .../src/snapshots/no_unused_vars@eslint.snap | 1 + .../no_unused_vars@oxc-arguments.snap | 1 + .../snapshots/no_unused_vars@oxc-classes.snap | 1 + .../snapshots/no_unused_vars@oxc-enums.snap | 1 + .../no_unused_vars@oxc-functions.snap | 1 + .../snapshots/no_unused_vars@oxc-imports.snap | 1 + .../no_unused_vars@oxc-namespaces.snap | 1 + .../no_unused_vars@oxc-self-call.snap | 1 + .../no_unused_vars@oxc-type-aliases.snap | 1 + .../no_unused_vars@oxc-type-references.snap | 1 + .../no_unused_vars@oxc-used-declarations.snap | 1 + .../no_unused_vars@oxc-vars-catch.snap | 1 + ...sed_vars@oxc-vars-destructure-ignored.snap | 50 - .../no_unused_vars@oxc-vars-destructure.snap | 1 + ...o_unused_vars@oxc-vars-discarded-read.snap | 1 + .../no_unused_vars@oxc-vars-reassignment.snap | 1 + .../no_unused_vars@oxc-vars-self-use.snap | 1 + .../no_unused_vars@oxc-vars-simple.snap | 1 + .../no_unused_vars@oxc-vars-using.snap | 1 + .../no_unused_vars@typescript-eslint-tsx.snap | 1 + .../no_unused_vars@typescript-eslint.snap | 1 + .../src/snapshots/no_unwanted_polyfillio.snap | 1 + .../src/snapshots/no_useless_catch.snap | 1 + .../src/snapshots/no_useless_concat.snap | 1 + .../src/snapshots/no_useless_constructor.snap | 1 + .../snapshots/no_useless_empty_export.snap | 1 + .../src/snapshots/no_useless_escape.snap | 1 + .../no_useless_fallback_in_spread.snap | 1 + .../snapshots/no_useless_length_check.snap | 1 + .../src/snapshots/no_useless_rename.snap | 1 + .../src/snapshots/no_useless_spread.snap | 1 + .../src/snapshots/no_useless_switch_case.snap | 1 + .../src/snapshots/no_useless_undefined.snap | 1 + crates/oxc_linter/src/snapshots/no_var.snap | 1 + .../src/snapshots/no_var_requires.snap | 1 + crates/oxc_linter/src/snapshots/no_void.snap | 1 + .../snapshots/no_webpack_loader_syntax.snap | 1 + crates/oxc_linter/src/snapshots/no_with.snap | 1 + .../snapshots/no_wrapper_object_types.snap | 1 + .../src/snapshots/no_zero_fractions.snap | 1 + .../snapshots/number_arg_out_of_range.snap | 1 + .../src/snapshots/number_literal_case.snap | 1 + .../snapshots/numeric_separators_style.snap | 1 + .../oxc_linter/src/snapshots/param_names.snap | 1 + .../snapshots/prefer_add_event_listener.snap | 1 + .../src/snapshots/prefer_array_flat.snap | 1 - .../src/snapshots/prefer_array_flat_map.snap | 1 + .../src/snapshots/prefer_array_some.snap | 1 + .../src/snapshots/prefer_as_const.snap | 1 + .../snapshots/prefer_await_to_callbacks.snap | 1 + .../src/snapshots/prefer_await_to_then.snap | 1 + .../prefer_blob_reading_methods.snap | 1 + .../src/snapshots/prefer_called_with.snap | 1 + .../src/snapshots/prefer_code_point.snap | 1 + .../snapshots/prefer_comparison_matcher.snap | 1 + .../src/snapshots/prefer_date_now.snap | 1 + .../src/snapshots/prefer_dom_node_append.snap | 1 + .../snapshots/prefer_dom_node_dataset.snap | 1 + .../src/snapshots/prefer_dom_node_remove.snap | 1 + .../prefer_dom_node_text_content.snap | 1 + .../oxc_linter/src/snapshots/prefer_each.snap | 1 + .../snapshots/prefer_enum_initializers.snap | 1 + .../snapshots/prefer_equality_matcher.snap | 1 + .../src/snapshots/prefer_es6_class.snap | 1 + .../src/snapshots/prefer_event_target.snap | 1 + .../src/snapshots/prefer_expect_resolves.snap | 1 + .../prefer_exponentiation_operator.snap | 1 + .../src/snapshots/prefer_for_of.snap | 1 + .../src/snapshots/prefer_function_type.snap | 1 + .../src/snapshots/prefer_hooks_in_order.snap | 1 + .../src/snapshots/prefer_hooks_on_top.snap | 1 + .../src/snapshots/prefer_includes.snap | 1 + .../src/snapshots/prefer_jest_mocked.snap | 3 +- .../snapshots/prefer_literal_enum_member.snap | 1 + .../prefer_logical_operator_over_ternary.snap | 1 + .../src/snapshots/prefer_lowercase_title.snap | 1 + .../src/snapshots/prefer_math_min_max.snap | 1 + .../src/snapshots/prefer_math_trunc.snap | 1 + .../prefer_mock_promise_shorthand.snap | 1 + .../src/snapshots/prefer_modern_dom_apis.snap | 1 + .../snapshots/prefer_modern_math_apis.snap | 1 + .../snapshots/prefer_namespace_keyword.snap | 1 + .../prefer_native_coercion_functions.snap | 1 + .../src/snapshots/prefer_node_protocol.snap | 1 + .../snapshots/prefer_number_properties.snap | 1 + .../snapshots/prefer_numeric_literals.snap | 1 + .../src/snapshots/prefer_object_has_own.snap | 2 +- .../prefer_optional_catch_binding.snap | 2 +- .../snapshots/prefer_prototype_methods.snap | 1 + .../src/snapshots/prefer_query_selector.snap | 1 + .../src/snapshots/prefer_reflect_apply.snap | 1 + .../src/snapshots/prefer_regexp_test.snap | 1 + .../src/snapshots/prefer_set_size.snap | 1 + .../src/snapshots/prefer_spread.snap | 1 + .../src/snapshots/prefer_spy_on.snap | 1 + .../src/snapshots/prefer_strict_equal.snap | 1 + .../snapshots/prefer_string_replace_all.snap | 1 + .../src/snapshots/prefer_string_slice.snap | 1 + .../prefer_string_starts_ends_with.snap | 1 + .../prefer_string_trim_start_end.snap | 1 + .../snapshots/prefer_structured_clone.snap | 1 + .../src/snapshots/prefer_tag_over_role.snap | 1 + .../src/snapshots/prefer_to_be.snap | 1 + .../src/snapshots/prefer_to_be_falsy.snap | 1 + .../src/snapshots/prefer_to_be_object.snap | 1 + .../src/snapshots/prefer_to_be_truthy.snap | 1 + .../src/snapshots/prefer_to_contain.snap | 1 + .../src/snapshots/prefer_to_have_length.snap | 1 + .../oxc_linter/src/snapshots/prefer_todo.snap | 1 + .../src/snapshots/prefer_ts_expect_error.snap | 1 + .../src/snapshots/prefer_type_error.snap | 1 + crates/oxc_linter/src/snapshots/radix.snap | 1 + .../src/snapshots/react_in_jsx_scope.snap | 1 + .../require_array_join_separator.snap | 1 + .../src/snapshots/require_await.snap | 1 + .../src/snapshots/require_hook.snap | 1 + ...test_context_for_concurrent_snapshots.snap | 1 + ...quire_number_to_fixed_digits_argument.snap | 1 + .../src/snapshots/require_param.snap | 1 + .../snapshots/require_param_description.snap | 1 + .../src/snapshots/require_param_name.snap | 1 + .../src/snapshots/require_param_type.snap | 1 + .../src/snapshots/require_property.snap | 1 + .../require_property_description.snap | 1 + .../src/snapshots/require_property_name.snap | 1 + .../src/snapshots/require_property_type.snap | 1 + .../src/snapshots/require_render_return.snap | 1 + .../src/snapshots/require_returns.snap | 1 + .../require_returns_description.snap | 1 + .../src/snapshots/require_returns_type.snap | 1 + .../snapshots/require_to_throw_message.snap | 1 + .../snapshots/require_top_level_describe.snap | 1 + .../src/snapshots/require_yield.snap | 1 + .../src/snapshots/require_yields.snap | 1 + .../role_has_required_aria_props.snap | 1 + .../snapshots/role_supports_aria_props.snap | 1 + .../src/snapshots/rules_of_hooks.snap | 1 + .../oxc_linter/src/snapshots/schema_json.snap | 1 + crates/oxc_linter/src/snapshots/scope.snap | 1 + .../src/snapshots/self_closing_comp.snap | 1 + .../src/snapshots/sort_imports.snap | 1 + .../oxc_linter/src/snapshots/sort_keys.snap | 1 + .../oxc_linter/src/snapshots/sort_vars.snap | 1 + .../oxc_linter/src/snapshots/spec_only.snap | 1 + .../src/snapshots/style_prop_object.snap | 1 + .../src/snapshots/switch_case_braces.snap | 1 + .../src/snapshots/symbol_description.snap | 1 + .../src/snapshots/tabindex_no_positive.snap | 1 + .../text_encoding_identifier_case.snap | 1 + .../src/snapshots/throw_new_error.snap | 1 + .../src/snapshots/triple_slash_reference.snap | 1 + .../oxc_linter/src/snapshots/unambiguous.snap | 1 + .../oxc_linter/src/snapshots/unicode_bom.snap | 1 + .../snapshots/uninvoked_array_callback.snap | 1 + .../oxc_linter/src/snapshots/use_isnan.snap | 1 + .../snapshots/valid_describe_callback.snap | 1 + .../src/snapshots/valid_expect.snap | 1 + .../src/snapshots/valid_params.snap | 1 + .../oxc_linter/src/snapshots/valid_title.snap | 1 + .../src/snapshots/valid_typeof.snap | 1 + .../void_dom_elements_no_children.snap | 1 + crates/oxc_linter/src/utils/mod.rs | 3 +- crates/oxc_linter/src/utils/tree_shaking.rs | 741 --------- .../src/utils/tree_shaking/pure_functions.rs | 370 ----- tasks/rulegen/src/main.rs | 10 +- tasks/rulegen/src/template.rs | 1 - 479 files changed, 468 insertions(+), 4738 deletions(-) delete mode 100644 crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs delete mode 100644 crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs delete mode 100644 crates/oxc_linter/src/snapshots/no_side_effects_in_initialization.snap delete mode 100644 crates/oxc_linter/src/snapshots/no_unused_vars@oxc-vars-destructure-ignored.snap delete mode 100644 crates/oxc_linter/src/utils/tree_shaking.rs delete mode 100644 crates/oxc_linter/src/utils/tree_shaking/pure_functions.rs diff --git a/crates/oxc_linter/src/context/mod.rs b/crates/oxc_linter/src/context/mod.rs index 3f57ce094773d1..6076b8767dea72 100644 --- a/crates/oxc_linter/src/context/mod.rs +++ b/crates/oxc_linter/src/context/mod.rs @@ -341,7 +341,6 @@ const PLUGIN_PREFIXES: phf::Map<&'static str, &'static str> = phf::phf_map! { "promise" => "eslint-plugin-promise", "react_perf" => "eslint-plugin-react-perf", "react" => "eslint-plugin-react", - "tree_shaking" => "eslint-plugin-tree-shaking", "typescript" => "typescript-eslint", "unicorn" => "eslint-plugin-unicorn", "vitest" => "eslint-plugin-vitest", diff --git a/crates/oxc_linter/src/rules.rs b/crates/oxc_linter/src/rules.rs index da52c309ce71d4..f9e39863d48f27 100644 --- a/crates/oxc_linter/src/rules.rs +++ b/crates/oxc_linter/src/rules.rs @@ -478,10 +478,6 @@ mod jsdoc { pub mod require_yields; } -mod tree_shaking { - pub mod no_side_effects_in_initialization; -} - mod promise { pub mod avoid_new; pub mod catch_or_return; @@ -830,7 +826,6 @@ oxc_macros::declare_all_lint_rules! { react_perf::jsx_no_new_function_as_prop, react_perf::jsx_no_new_object_as_prop, security::api_keys, - tree_shaking::no_side_effects_in_initialization, typescript::adjacent_overload_signatures, typescript::array_type, typescript::ban_ts_comment, 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 deleted file mode 100644 index 0e898d1fa1065f..00000000000000 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/listener_map.rs +++ /dev/null @@ -1,1354 +0,0 @@ -use oxc_ast::{ - ast::{ - match_declaration, match_expression, match_member_expression, - match_simple_assignment_target, Argument, ArrayExpressionElement, ArrowFunctionExpression, - AssignmentTarget, BinaryExpression, BindingIdentifier, BindingPattern, BindingPatternKind, - CallExpression, Class, ClassBody, ClassElement, ComputedMemberExpression, - ConditionalExpression, Declaration, ExportSpecifier, Expression, ForStatementInit, - FormalParameter, Function, IdentifierReference, JSXAttribute, JSXAttributeItem, - JSXAttributeValue, JSXChild, JSXElement, JSXElementName, JSXExpression, - JSXExpressionContainer, JSXFragment, JSXMemberExpression, JSXOpeningElement, - LogicalExpression, MemberExpression, ModuleExportName, NewExpression, ObjectExpression, - ObjectPropertyKind, ParenthesizedExpression, PrivateFieldExpression, Program, PropertyKey, - SequenceExpression, SimpleAssignmentTarget, Statement, StaticMemberExpression, SwitchCase, - ThisExpression, UnaryExpression, VariableDeclarator, - }, - AstKind, -}; -use oxc_semantic::{AstNode, NodeId}; -use oxc_span::{GetSpan, Span}; -use oxc_syntax::operator::{LogicalOperator, UnaryOperator}; - -use crate::{ - ast_util::{get_declaration_of_variable, get_symbol_id_of_variable}, - utils::{ - calculate_binary_operation, calculate_logical_operation, calculate_unary_operation, - get_write_expr, has_comment_about_side_effect_check, has_pure_notation, - is_function_side_effect_free, is_local_variable_a_whitelisted_module, is_pure_function, - no_effects, FunctionName, NodeListenerOptions, Value, - }, -}; - -pub trait ListenerMap<'a> { - fn report_effects(&self, _options: &NodeListenerOptions<'a, '_>) {} - fn report_effects_when_assigned(&self, _options: &NodeListenerOptions<'a, '_>) {} - fn report_effects_when_called(&self, _options: &NodeListenerOptions<'a, '_>) {} - fn report_effects_when_mutated(&self, _options: &NodeListenerOptions<'a, '_>) {} - fn get_value_and_report_effects(&self, _options: &NodeListenerOptions<'a, '_>) -> Value { - Value::Unknown - } -} - -impl<'a> ListenerMap<'a> for Program<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.body.iter().for_each(|stmt| stmt.report_effects(options)); - } -} - -impl<'a> ListenerMap<'a> for Statement<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ExpressionStatement(expr_stmt) => { - expr_stmt.expression.report_effects(options); - } - #[allow(clippy::match_same_arms)] - Self::BreakStatement(_) | Self::ContinueStatement(_) | Self::EmptyStatement(_) => { - no_effects(); - } - match_declaration!(Self) => self.to_declaration().report_effects(options), - Self::ReturnStatement(stmt) => { - if let Some(arg) = &stmt.argument { - arg.report_effects(options); - } - } - Self::ExportAllDeclaration(_) | Self::ImportDeclaration(_) => { - no_effects(); - } - Self::ExportDefaultDeclaration(stmt) => { - if let Some(expr) = &stmt.declaration.as_expression() { - if has_comment_about_side_effect_check(expr.span(), options.ctx) { - expr.report_effects_when_called(options); - } - expr.report_effects(options); - } - } - Self::ExportNamedDeclaration(stmt) => { - stmt.specifiers.iter().for_each(|specifier| { - specifier.report_effects(options); - }); - - if let Some(decl) = &stmt.declaration { - decl.report_effects(options); - } - } - Self::TryStatement(stmt) => { - stmt.block.body.iter().for_each(|stmt| stmt.report_effects(options)); - stmt.handler.iter().for_each(|handler| { - handler.body.body.iter().for_each(|stmt| stmt.report_effects(options)); - }); - stmt.finalizer.iter().for_each(|finalizer| { - finalizer.body.iter().for_each(|stmt| stmt.report_effects(options)); - }); - } - Self::ThrowStatement(stmt) => { - options.ctx.diagnostic(super::throw(stmt.span)); - } - Self::BlockStatement(stmt) => { - stmt.body.iter().for_each(|stmt| stmt.report_effects(options)); - } - Self::IfStatement(stmt) => { - let test_result = stmt.test.get_value_and_report_effects(options); - - if let Some(is_falsy) = test_result.get_falsy_value() { - if is_falsy { - if let Some(alternate) = &stmt.alternate { - alternate.report_effects(options); - } - } else { - stmt.consequent.report_effects(options); - } - } else { - stmt.consequent.report_effects(options); - if let Some(alternate) = &stmt.alternate { - alternate.report_effects(options); - } - } - } - Self::DoWhileStatement(stmt) => { - if stmt - .test - .get_value_and_report_effects(options) - .get_falsy_value() - .is_some_and(|is_falsy| is_falsy) - { - return; - } - stmt.body.report_effects(options); - } - Self::DebuggerStatement(stmt) => { - options.ctx.diagnostic(super::debugger(stmt.span)); - } - Self::ForStatement(stmt) => { - if let Some(init) = &stmt.init { - init.report_effects(options); - } - if let Some(test) = &stmt.test { - test.report_effects(options); - } - if let Some(update) = &stmt.update { - update.report_effects(options); - } - stmt.body.report_effects(options); - } - Self::ForInStatement(stmt) => { - if let Some(assign) = stmt.left.as_assignment_target() { - assign.report_effects_when_assigned(options); - } - stmt.right.report_effects(options); - stmt.body.report_effects(options); - } - Self::ForOfStatement(stmt) => { - if let Some(assign) = stmt.left.as_assignment_target() { - assign.report_effects_when_assigned(options); - } - stmt.right.report_effects(options); - stmt.body.report_effects(options); - } - Self::LabeledStatement(stmt) => { - stmt.body.report_effects(options); - } - Self::WhileStatement(stmt) => { - if stmt - .test - .get_value_and_report_effects(options) - .get_falsy_value() - .is_some_and(|is_falsy| is_falsy) - { - return; - } - stmt.body.report_effects(options); - } - Self::SwitchStatement(stmt) => { - stmt.discriminant.report_effects(options); - stmt.cases.iter().for_each(|case| { - case.report_effects(options); - }); - } - _ => {} - } - } -} - -impl<'a> ListenerMap<'a> for ForStatementInit<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - match_expression!(Self) => self.to_expression().report_effects(options), - Self::VariableDeclaration(decl) => { - decl.declarations.iter().for_each(|decl| decl.report_effects(options)); - } - } - } -} - -impl<'a> ListenerMap<'a> for ExportSpecifier<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - let ctx = options.ctx; - let symbol_table = ctx.symbols(); - if has_comment_about_side_effect_check(self.exported.span(), ctx) { - let ModuleExportName::IdentifierReference(ident) = &self.local else { - return; - }; - let Some(symbol_id) = get_symbol_id_of_variable(ident, ctx) else { - return; - }; - - 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); - } - } -} - -// we don't need implement all AstNode -// it's same as `reportSideEffectsInDefinitionWhenCalled` in eslint-plugin-tree-shaking -// -impl<'a> ListenerMap<'a> for AstNode<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - match self.kind() { - AstKind::VariableDeclarator(decl) => { - if let Some(init) = &decl.init { - init.report_effects_when_called(options); - } - } - AstKind::FormalParameter(param) => { - options.ctx.diagnostic(super::call_parameter(param.span)); - } - AstKind::BindingRestElement(rest) => { - let start = rest.span.start + 3; - let end = rest.span.end; - options.ctx.diagnostic(super::call_parameter(Span::new(start, end))); - } - AstKind::Function(function) => { - let old_val = options.has_valid_this.get(); - options.has_valid_this.set(options.called_with_new.get()); - function.report_effects_when_called(options); - options.has_valid_this.set(old_val); - } - AstKind::Class(class) => { - class.report_effects_when_called(options); - } - AstKind::ImportDefaultSpecifier(specifier) => { - report_on_imported_call( - specifier.local.span, - &specifier.local.name, - self.id(), - options, - ); - } - AstKind::ImportSpecifier(specifier) => { - report_on_imported_call( - specifier.local.span, - &specifier.local.name, - self.id(), - options, - ); - } - AstKind::ImportNamespaceSpecifier(specifier) => { - report_on_imported_call( - specifier.local.span, - &specifier.local.name, - self.id(), - options, - ); - } - _ => {} - } - } - - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - match self.kind() { - AstKind::VariableDeclarator(decl) => { - if let Some(init) = &decl.init { - init.report_effects_when_mutated(options); - } - } - AstKind::FormalParameter(param) => { - options.ctx.diagnostic(super::mutate_parameter(param.span)); - } - AstKind::BindingRestElement(rest) => { - let start = rest.span.start + 3; - let end = rest.span.end; - options.ctx.diagnostic(super::mutate_parameter(Span::new(start, end))); - } - AstKind::ImportDefaultSpecifier(specifier) => { - options.ctx.diagnostic(super::mutate_import(specifier.span)); - } - AstKind::ImportSpecifier(specifier) => { - options.ctx.diagnostic(super::mutate_import(specifier.local.span)); - } - AstKind::ImportNamespaceSpecifier(specifier) => { - options.ctx.diagnostic(super::mutate_import(specifier.local.span)); - } - _ => {} - } - } -} - -fn report_on_imported_call(span: Span, name: &str, node_id: NodeId, options: &NodeListenerOptions) { - if has_comment_about_side_effect_check(span, options.ctx) { - return; - } - let Some(AstKind::ImportDeclaration(decl)) = options.ctx.nodes().parent_kind(node_id) else { - return; - }; - if is_function_side_effect_free(name, &decl.source.value, options) { - return; - } - options.ctx.diagnostic(super::call_import(span)); -} - -impl<'a> ListenerMap<'a> for Declaration<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::VariableDeclaration(decl) => { - decl.declarations.iter().for_each(|decl| decl.report_effects(options)); - } - Self::ClassDeclaration(decl) => { - decl.report_effects(options); - } - Self::FunctionDeclaration(function) => { - if let Some(id) = &function.id { - if has_comment_about_side_effect_check(id.span, options.ctx) { - id.report_effects_when_called(options); - } - } - } - _ => {} - } - } -} - -impl<'a> ListenerMap<'a> for Class<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - if let Some(super_class) = &self.super_class { - super_class.report_effects(options); - } - self.body.report_effects(options); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - if let Some(super_class) = &self.super_class { - super_class.report_effects_when_called(options); - } - self.body.report_effects_when_called(options); - } -} - -impl<'a> ListenerMap<'a> for ClassBody<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.body.iter().for_each(|class_element| { - class_element.report_effects(options); - }); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - let constructor = self.body.iter().find(|class_element| { - if let ClassElement::MethodDefinition(definition) = class_element { - return definition.kind.is_constructor(); - } - false - }); - - if let Some(constructor) = constructor { - let old_val = options.has_valid_this.get(); - options.has_valid_this.set(options.called_with_new.get()); - constructor.report_effects_when_called(options); - options.has_valid_this.set(old_val); - } - - self.body - .iter() - .filter(|class_element| matches!(class_element, ClassElement::PropertyDefinition(_))) - .for_each(|property_definition| { - property_definition.report_effects_when_called(options); - }); - } -} - -impl<'a> ListenerMap<'a> for ClassElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::MethodDefinition(method) => { - method.key.report_effects(options); - } - Self::PropertyDefinition(prop) => { - prop.key.report_effects(options); - } - _ => {} - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::MethodDefinition(method) => { - method.value.report_effects_when_called(options); - } - Self::PropertyDefinition(prop) => { - if let Some(value) = &prop.value { - value.report_effects_when_called(options); - } - } - _ => {} - } - } -} - -impl<'a> ListenerMap<'a> for PropertyKey<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self.as_expression() { - Some(expr) => expr.report_effects(options), - None => no_effects(), - } - } -} - -impl<'a> ListenerMap<'a> for VariableDeclarator<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.id.report_effects(options); - if has_comment_about_side_effect_check(self.id.span(), options.ctx) { - self.id.report_effects_when_called(options); - } - - if let Some(init) = &self.init { - init.report_effects(options); - } - } -} - -impl<'a> ListenerMap<'a> for BindingPattern<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match &self.kind { - BindingPatternKind::BindingIdentifier(_) => {} - BindingPatternKind::ArrayPattern(array) => { - array.elements.iter().for_each(|el| { - if let Some(el) = el { - el.report_effects(options); - } - }); - } - BindingPatternKind::ObjectPattern(object) => { - object.properties.iter().for_each(|prop| { - prop.key.report_effects(options); - prop.value.report_effects(options); - }); - } - BindingPatternKind::AssignmentPattern(assign_p) => { - assign_p.left.report_effects(options); - assign_p.right.report_effects(options); - } - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - if let BindingPatternKind::BindingIdentifier(ident) = &self.kind { - ident.report_effects_when_called(options); - } - } -} - -impl<'a> ListenerMap<'a> for BindingIdentifier<'a> { - fn report_effects(&self, _options: &NodeListenerOptions<'a, '_>) { - no_effects(); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - let ctx = options.ctx; - if let Some(symbol_id) = self.symbol_id.get() { - 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 node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id)); - node.report_effects_when_called(options); - } - } -} - -impl<'a> ListenerMap<'a> for Expression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ArrayExpression(array_expr) => { - array_expr.elements.iter().for_each(|el| el.report_effects(options)); - } - Self::AssignmentExpression(assign_expr) => { - assign_expr.left.report_effects_when_assigned(options); - assign_expr.right.report_effects(options); - } - Self::CallExpression(call_expr) => { - call_expr.report_effects(options); - } - Self::ParenthesizedExpression(expr) => { - expr.report_effects(options); - } - Self::NewExpression(expr) => { - expr.report_effects(options); - } - Self::AwaitExpression(expr) => { - expr.argument.report_effects(options); - } - Self::BinaryExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::ClassExpression(expr) => { - expr.report_effects(options); - } - Self::ConditionalExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::JSXElement(expr) => { - expr.report_effects(options); - } - Self::ObjectExpression(expr) => { - expr.report_effects(options); - } - Self::LogicalExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::StaticMemberExpression(expr) => { - expr.report_effects(options); - } - Self::ComputedMemberExpression(expr) => { - expr.report_effects(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects(options); - } - Self::UnaryExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::UpdateExpression(expr) => { - expr.argument.report_effects_when_assigned(options); - } - Self::SequenceExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::YieldExpression(expr) => { - expr.argument.iter().for_each(|arg| arg.report_effects(options)); - } - Self::TaggedTemplateExpression(expr) => { - expr.tag.report_effects_when_called(options); - expr.quasi.expressions.iter().for_each(|expr| { - expr.report_effects(options); - }); - } - Self::TemplateLiteral(expr) => { - expr.expressions.iter().for_each(|expr| { - expr.report_effects(options); - }); - } - Self::ArrowFunctionExpression(_) - | Self::FunctionExpression(_) - | Self::Identifier(_) - | Self::MetaProperty(_) - | Self::Super(_) - | Self::ThisExpression(_) => no_effects(), - _ => {} - } - } - - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::Identifier(ident) => { - ident.report_effects_when_mutated(options); - } - Self::ArrowFunctionExpression(_) | Self::ObjectExpression(_) => no_effects(), - Self::ParenthesizedExpression(expr) => { - expr.report_effects_when_mutated(options); - } - Self::CallExpression(expr) => { - expr.report_effects_when_mutated(options); - } - Self::ThisExpression(expr) => { - expr.report_effects_when_mutated(options); - } - _ => { - // Default behavior - options.ctx.diagnostic(super::mutate(self.span())); - } - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::CallExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::Identifier(expr) => { - expr.report_effects_when_called(options); - } - Self::FunctionExpression(expr) => { - let old_val = options.has_valid_this.get(); - options.has_valid_this.set(options.called_with_new.get()); - expr.report_effects_when_called(options); - options.has_valid_this.set(old_val); - } - Self::ArrowFunctionExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::ParenthesizedExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::ClassExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::ConditionalExpression(expr) => expr.report_effects_when_called(options), - Self::StaticMemberExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::ComputedMemberExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects_when_called(options); - } - _ => { - // Default behavior - options.ctx.diagnostic(super::call(self.span())); - } - } - } - - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - match self { - Self::BooleanLiteral(_) - | Self::StringLiteral(_) - | Self::NumericLiteral(_) - | Self::TemplateLiteral(_) => Value::new(self), - Self::BinaryExpression(expr) => expr.get_value_and_report_effects(options), - Self::ConditionalExpression(expr) => expr.get_value_and_report_effects(options), - Self::LogicalExpression(expr) => expr.get_value_and_report_effects(options), - Self::SequenceExpression(expr) => expr.get_value_and_report_effects(options), - _ => { - self.report_effects(options); - Value::Unknown - } - } - } -} - -// which kind of Expression defines `report_effects_when_called` method. -fn defined_custom_report_effects_when_called(expr: &Expression) -> bool { - matches!( - expr.get_inner_expression(), - Expression::ArrowFunctionExpression(_) - | Expression::CallExpression(_) - | Expression::ClassExpression(_) - | Expression::ConditionalExpression(_) - | Expression::FunctionExpression(_) - | Expression::Identifier(_) - | Expression::ComputedMemberExpression(_) - | Expression::StaticMemberExpression(_) - | Expression::PrivateFieldExpression(_) - ) -} - -impl<'a> ListenerMap<'a> for SwitchCase<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - if let Some(test) = &self.test { - test.report_effects(options); - } - self.consequent.iter().for_each(|stmt| { - stmt.report_effects(options); - }); - } -} - -impl<'a> ListenerMap<'a> for SequenceExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - let mut val = Value::Unknown; - for expr in &self.expressions { - val = expr.get_value_and_report_effects(options); - } - val - } -} - -impl<'a> ListenerMap<'a> for UnaryExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - if self.operator == UnaryOperator::Delete { - match &self.argument { - Expression::StaticMemberExpression(expr) => { - expr.object.report_effects_when_mutated(options); - } - Expression::ComputedMemberExpression(expr) => { - expr.object.report_effects_when_mutated(options); - } - Expression::PrivateFieldExpression(expr) => { - expr.object.report_effects_when_mutated(options); - } - _ => options.ctx.diagnostic(super::delete(self.argument.span())), - } - return Value::Unknown; - } - - let value = self.argument.get_value_and_report_effects(options); - calculate_unary_operation(self.operator, value) - } -} - -impl<'a> ListenerMap<'a> for LogicalExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - let left = self.left.get_value_and_report_effects(options); - // `false && foo` - if self.operator == LogicalOperator::And - && left.get_falsy_value().is_some_and(|is_falsy| is_falsy) - { - return left; - } - // `true || foo` - if self.operator == LogicalOperator::Or - && left.get_falsy_value().is_some_and(|is_falsy| !is_falsy) - { - return left; - } - let right = self.right.get_value_and_report_effects(options); - calculate_logical_operation(self.operator, left, right) - } -} - -impl<'a> ListenerMap<'a> for ObjectExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.properties.iter().for_each(|property| match property { - ObjectPropertyKind::ObjectProperty(p) => { - p.key.report_effects(options); - p.value.report_effects(options); - } - ObjectPropertyKind::SpreadProperty(spreed) => { - spreed.argument.report_effects(options); - } - }); - } -} - -impl<'a> ListenerMap<'a> for JSXElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.opening_element.report_effects(options); - self.children.iter().for_each(|child| { - child.report_effects(options); - }); - } -} - -impl<'a> ListenerMap<'a> for JSXChild<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - JSXChild::Element(element) => { - element.report_effects(options); - } - JSXChild::Spread(spread) => { - spread.expression.report_effects(options); - } - JSXChild::Fragment(fragment) => { - fragment.report_effects(options); - } - JSXChild::ExpressionContainer(container) => { - container.report_effects(options); - } - JSXChild::Text(_) => { - no_effects(); - } - } - } -} - -impl<'a> ListenerMap<'a> for JSXOpeningElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.name.report_effects_when_called(options); - self.attributes.iter().for_each(|attr| attr.report_effects(options)); - } -} - -impl<'a> ListenerMap<'a> for JSXElementName<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::Identifier(_) | Self::NamespacedName(_) => {} - Self::IdentifierReference(ident) => ident.report_effects_when_called(options), - Self::MemberExpression(member) => member.report_effects_when_called(options), - Self::ThisExpression(expr) => expr.report_effects_when_called(options), - } - } -} - -impl<'a> ListenerMap<'a> for JSXMemberExpression<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - options.ctx.diagnostic(super::call_member(self.property.span())); - } -} - -impl<'a> ListenerMap<'a> for JSXAttributeItem<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::Attribute(attribute) => { - attribute.report_effects(options); - } - Self::SpreadAttribute(attribute) => { - attribute.argument.report_effects(options); - } - } - } -} - -impl<'a> ListenerMap<'a> for JSXAttribute<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - if let Some(value) = &self.value { - match value { - JSXAttributeValue::ExpressionContainer(container) => { - container.report_effects(options); - } - JSXAttributeValue::Element(element) => { - element.report_effects(options); - } - JSXAttributeValue::Fragment(fragment) => { - fragment.report_effects(options); - } - JSXAttributeValue::StringLiteral(_) => { - no_effects(); - } - } - } - } -} - -impl<'a> ListenerMap<'a> for JSXExpressionContainer<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects(options); - } -} - -impl<'a> ListenerMap<'a> for JSXExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ArrayExpression(array_expr) => { - array_expr.elements.iter().for_each(|el| el.report_effects(options)); - } - Self::AssignmentExpression(assign_expr) => { - assign_expr.left.report_effects_when_assigned(options); - assign_expr.right.report_effects(options); - } - Self::CallExpression(call_expr) => { - call_expr.report_effects(options); - } - Self::ParenthesizedExpression(expr) => { - expr.report_effects(options); - } - Self::NewExpression(expr) => { - expr.report_effects(options); - } - Self::AwaitExpression(expr) => { - expr.argument.report_effects(options); - } - Self::BinaryExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::ClassExpression(expr) => { - expr.report_effects(options); - } - Self::ConditionalExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::JSXElement(expr) => { - expr.report_effects(options); - } - Self::ObjectExpression(expr) => { - expr.report_effects(options); - } - Self::StaticMemberExpression(expr) => { - expr.report_effects(options); - } - Self::ComputedMemberExpression(expr) => { - expr.report_effects(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects(options); - } - Self::UnaryExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::SequenceExpression(expr) => { - expr.get_value_and_report_effects(options); - } - Self::ArrowFunctionExpression(_) - | Self::EmptyExpression(_) - | Self::FunctionExpression(_) - | Self::Identifier(_) - | Self::MetaProperty(_) - | Self::Super(_) - | Self::ThisExpression(_) => no_effects(), - _ => {} - } - } -} - -impl<'a> ListenerMap<'a> for JSXFragment<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.children.iter().for_each(|child| child.report_effects(options)); - } -} - -impl<'a> ListenerMap<'a> for ConditionalExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - let test_result = self.test.get_value_and_report_effects(options); - - if let Some(is_falsy) = test_result.get_falsy_value() { - if is_falsy { - self.alternate.get_value_and_report_effects(options) - } else { - self.consequent.get_value_and_report_effects(options) - } - } else { - self.consequent.report_effects(options); - self.alternate.report_effects(options); - test_result - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - let test_result = self.test.get_value_and_report_effects(options); - - if let Some(falsy) = test_result.get_falsy_value() { - if falsy { - self.alternate.report_effects_when_called(options); - } else { - self.consequent.report_effects_when_called(options); - } - } else { - self.consequent.report_effects_when_called(options); - self.alternate.report_effects_when_called(options); - } - } -} - -impl<'a> ListenerMap<'a> for BinaryExpression<'a> { - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - let left = self.left.get_value_and_report_effects(options); - let right = self.right.get_value_and_report_effects(options); - calculate_binary_operation(self.operator, left, right) - } -} - -impl<'a> ListenerMap<'a> for ThisExpression { - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - if !options.has_valid_this.get() { - options.ctx.diagnostic(super::mutate_of_this(self.span)); - } - } -} - -impl<'a> ListenerMap<'a> for NewExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - if has_pure_notation(self.span, options.ctx) { - return; - } - self.arguments.iter().for_each(|arg| arg.report_effects(options)); - let old_val = options.called_with_new.get(); - options.called_with_new.set(true); - self.callee.report_effects_when_called(options); - options.called_with_new.set(old_val); - } -} - -impl<'a> ListenerMap<'a> for ParenthesizedExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects(options); - } - - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects_when_assigned(options); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects_when_called(options); - } - - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects_when_mutated(options); - } - - fn get_value_and_report_effects(&self, options: &NodeListenerOptions<'a, '_>) -> Value { - self.expression.get_value_and_report_effects(options) - } -} - -impl<'a> ListenerMap<'a> for ArrowFunctionExpression<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.params.items.iter().for_each(|param| param.report_effects(options)); - self.body.statements.iter().for_each(|stmt| stmt.report_effects(options)); - } -} - -impl<'a> ListenerMap<'a> for Function<'a> { - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.params.items.iter().for_each(|param| param.report_effects(options)); - - if let Some(body) = &self.body { - body.statements.iter().for_each(|stmt| stmt.report_effects(options)); - } - } -} - -impl<'a> ListenerMap<'a> for FormalParameter<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.pattern.report_effects(options); - } -} - -impl<'a> ListenerMap<'a> for CallExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.arguments.iter().for_each(|arg| arg.report_effects(options)); - if defined_custom_report_effects_when_called(&self.callee) { - let old_value = options.called_with_new.get(); - options.called_with_new.set(false); - self.callee.report_effects_when_called(options); - options.called_with_new.set(old_value); - } else { - options.ctx.diagnostic(super::call(self.callee.span())); - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - let ctx = options.ctx; - if let Expression::Identifier(ident) = &self.callee { - if let Some(node) = get_declaration_of_variable(ident, ctx) { - if is_local_variable_a_whitelisted_module(node, ident.name.as_str(), options) { - return; - } - options.ctx.diagnostic(super::call_return_value(self.span)); - } else { - options.ctx.diagnostic(super::call_return_value(self.span)); - } - } - } - - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - options.ctx.diagnostic(super::mutate_function_return_value(self.span)); - } -} - -impl<'a> ListenerMap<'a> for Argument<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - match_expression!(Self) => self.to_expression().report_effects(options), - Self::SpreadElement(spread) => { - spread.argument.report_effects(options); - } - } - } -} - -impl<'a> ListenerMap<'a> for AssignmentTarget<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - match_simple_assignment_target!(Self) => { - self.to_simple_assignment_target().report_effects_when_assigned(options); - } - Self::ArrayAssignmentTarget(_) | Self::ObjectAssignmentTarget(_) => {} - } - } -} - -impl<'a> ListenerMap<'a> for SimpleAssignmentTarget<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::AssignmentTargetIdentifier(ident) => { - ident.report_effects_when_assigned(options); - } - match_member_expression!(Self) => { - self.to_member_expression().report_effects_when_assigned(options); - } - _ => { - // For remain TypeScript AST, just visit its expression - if let Some(expr) = self.get_expression() { - expr.report_effects_when_assigned(options); - } - } - } - } -} - -impl<'a> ListenerMap<'a> for IdentifierReference<'a> { - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - if get_symbol_id_of_variable(self, options.ctx).is_none() { - options.ctx.diagnostic(super::assignment(self.name.as_str(), self.span)); - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - if is_pure_function(&FunctionName::Identifier(self), options) { - return; - } - - let ctx = options.ctx; - - if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) { - let is_used_in_jsx = matches!( - ctx.nodes().parent_kind( - ctx.symbols().get_reference(self.reference_id.get().unwrap()).node_id() - ), - Some(AstKind::JSXElementName(_) | AstKind::JSXMemberExpressionObject(_)) - ); - - if is_used_in_jsx { - for reference in options.ctx.symbols().get_resolved_references(symbol_id) { - if reference.is_write() { - let node_id = reference.node_id(); - if let Some(expr) = get_write_expr(node_id, options.ctx) { - let old_val = options.called_with_new.get(); - options.called_with_new.set(true); - expr.report_effects_when_called(options); - options.called_with_new.set(old_val); - } - } - } - let symbol_table = options.ctx.semantic().symbols(); - let node = options.ctx.nodes().get_node(symbol_table.get_declaration(symbol_id)); - let old_val = options.called_with_new.get(); - options.called_with_new.set(true); - node.report_effects_when_called(options); - options.called_with_new.set(old_val); - return; - } - - if options.insert_called_node(symbol_id) { - 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(super::call_global(self.name.as_str(), self.span)); - } - } - - fn report_effects_when_mutated(&self, options: &NodeListenerOptions<'a, '_>) { - let ctx = options.ctx; - if let Some(symbol_id) = get_symbol_id_of_variable(self, ctx) { - if options.insert_mutated_node(symbol_id) { - for reference in ctx.symbols().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_mutated(options); - } - } - } - - let symbol_table = ctx.semantic().symbols(); - let node = ctx.nodes().get_node(symbol_table.get_declaration(symbol_id)); - node.report_effects_when_mutated(options); - } - } else { - ctx.diagnostic(super::mutate_with_name(self.name.as_str(), self.span)); - } - } -} - -impl<'a> ListenerMap<'a> for MemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ComputedMemberExpression(expr) => { - expr.report_effects(options); - } - Self::StaticMemberExpression(expr) => { - expr.report_effects(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects(options); - } - } - } - - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ComputedMemberExpression(expr) => { - expr.report_effects_when_assigned(options); - } - Self::StaticMemberExpression(expr) => { - expr.report_effects_when_assigned(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects_when_assigned(options); - } - } - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - Self::ComputedMemberExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::StaticMemberExpression(expr) => { - expr.report_effects_when_called(options); - } - Self::PrivateFieldExpression(expr) => { - expr.report_effects_when_called(options); - } - } - } -} - -impl<'a> ListenerMap<'a> for ComputedMemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.expression.report_effects(options); - self.object.report_effects(options); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - - let mut node = &self.object; - loop { - match node { - Expression::ComputedMemberExpression(expr) => { - node = &expr.object; - } - Expression::StaticMemberExpression(expr) => node = &expr.object, - Expression::PrivateInExpression(expr) => node = &expr.right, - _ => { - break; - } - } - } - - if let Expression::Identifier(ident) = node { - ident.report_effects_when_called(options); - } else { - options.ctx.diagnostic(super::call_member(node.span())); - } - } - - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - self.object.report_effects_when_mutated(options); - } -} - -impl<'a> ListenerMap<'a> for StaticMemberExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.object.report_effects(options); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - - let mut root_member_expr = &self.object; - loop { - match root_member_expr { - Expression::ComputedMemberExpression(expr) => { - root_member_expr = &expr.object; - } - Expression::StaticMemberExpression(expr) => root_member_expr = &expr.object, - Expression::PrivateInExpression(expr) => root_member_expr = &expr.right, - _ => { - break; - } - } - } - - let Expression::Identifier(ident) = root_member_expr else { - options.ctx.diagnostic(super::call_member(root_member_expr.span())); - return; - }; - - let Some(node) = get_declaration_of_variable(ident, options.ctx) else { - // If the variable is not declared, it is a global variable. - // `ext.x()` - if !is_pure_function(&FunctionName::StaticMemberExpr(self), options) { - options.ctx.diagnostic(super::call_member(self.span)); - } - return; - }; - - if is_local_variable_a_whitelisted_module(node, &ident.name, options) { - return; - }; - - if has_pure_notation(self.span, options.ctx) { - return; - } - - options.ctx.diagnostic(super::call_member(self.span)); - } - - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - self.object.report_effects_when_mutated(options); - } -} - -impl<'a> ListenerMap<'a> for PrivateFieldExpression<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - self.object.report_effects(options); - } - - fn report_effects_when_called(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - - let mut node = &self.object; - loop { - match node { - Expression::ComputedMemberExpression(expr) => { - node = &expr.object; - } - Expression::StaticMemberExpression(expr) => node = &expr.object, - Expression::PrivateInExpression(expr) => node = &expr.right, - _ => { - break; - } - } - } - - if let Expression::Identifier(ident) = node { - ident.report_effects_when_called(options); - } else { - options.ctx.diagnostic(super::call_member(node.span())); - } - } - - fn report_effects_when_assigned(&self, options: &NodeListenerOptions<'a, '_>) { - self.report_effects(options); - self.object.report_effects_when_mutated(options); - } -} - -impl<'a> ListenerMap<'a> for ArrayExpressionElement<'a> { - fn report_effects(&self, options: &NodeListenerOptions<'a, '_>) { - match self { - match_expression!(Self) => self.to_expression().report_effects(options), - Self::SpreadElement(spreed) => { - spreed.argument.report_effects(options); - } - Self::Elision(_) => {} - } - } -} 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 deleted file mode 100644 index be2dab30c97f28..00000000000000 --- a/crates/oxc_linter/src/rules/tree_shaking/no_side_effects_in_initialization/mod.rs +++ /dev/null @@ -1,896 +0,0 @@ -use oxc_ast::AstKind; -use oxc_diagnostics::OxcDiagnostic; -use oxc_macros::declare_oxc_lint; -use oxc_span::Span; -use serde_json::Value; - -use self::listener_map::ListenerMap; -use crate::{ - context::LintContext, - rule::Rule, - utils::{ModuleFunctions, NodeListenerOptions, WhitelistModule}, -}; - -mod listener_map; - -fn assignment(x0: &str, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::warn(format!("Cannot determine side-effects of assignment to `{x0}`")) - .with_label(span1) -} - -fn mutate(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of mutating").with_label(span) -} - -fn mutate_with_name(x0: &str, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::warn(format!("Cannot determine side-effects of mutating `{x0}`")) - .with_label(span1) -} - -fn mutate_function_return_value(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of mutating function return value") - .with_label(span) -} - -fn mutate_parameter(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of mutating function parameter") - .with_label(span) -} - -fn mutate_of_this(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of mutating unknown this value") - .with_label(span) -} - -fn mutate_import(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of mutating imported variable") - .with_label(span) -} - -fn call(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of calling").with_label(span) -} - -fn call_return_value(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of calling function return value") - .with_label(span) -} - -fn call_global(x0: &str, span1: Span) -> OxcDiagnostic { - OxcDiagnostic::warn(format!("Cannot determine side-effects of calling global function `{x0}`")) - .with_label(span1) -} - -fn call_parameter(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of calling function parameter") - .with_label(span) -} - -fn call_import(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of calling imported function") - .with_label(span) -} - -fn call_member(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of calling member function").with_label(span) -} - -fn debugger(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Debugger statements are side-effects").with_label(span) -} - -fn delete(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Cannot determine side-effects of deleting anything but a MemberExpression") - .with_label(span) -} - -fn throw(span: Span) -> OxcDiagnostic { - OxcDiagnostic::warn("Throwing an error is a side-effect").with_label(span) -} - -/// -#[derive(Debug, Default, Clone)] -pub struct NoSideEffectsInInitialization(Box); - -impl std::ops::Deref for NoSideEffectsInInitialization { - type Target = NoSideEffectsInInitiallizationOptions; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -#[derive(Debug, Default, Clone)] -pub struct NoSideEffectsInInitiallizationOptions { - functions: Vec, - modules: Vec, -} - -declare_oxc_lint!( - /// ### What it does - /// - /// Marks all side-effects in module initialization that will interfere with tree-shaking. - /// - /// This plugin is intended as a means for library developers to identify patterns that will - /// interfere with the tree-shaking algorithm of their module bundler (i.e. rollup or webpack). - /// - /// ### Why is this bad? - /// - /// Side-effects in module initialization can hinder tree-shaking, which aims to remove - /// unused code. If side-effects exist, it's harder for the bundler to safely eliminate - /// code, leading to larger bundles and potentially unexpected behavior. Ensuring minimal - /// side-effects allows bundlers to optimize code effectively. - /// - /// ### Examples - /// - /// Examples of **incorrect** code for this rule: - /// ```javascript - /// myGlobal = 17; // Cannot determine side-effects of assignment to global variable - /// const x = { [globalFunction()]: "myString" }; // Cannot determine side-effects of calling global function - /// ``` - /// - /// Examples of **correct** code for this rule: - /// ```javascript - /// const localVar = 17; // Local variable assignment, no global side-effects - /// export default 42; // Pure export with no side-effects - /// ``` - /// - /// ### Options - /// - /// ```json - /// { - /// "rules": { - /// "tree-shaking/no-side-effects-in-initialization": [ - /// 2, - /// { - /// "noSideEffectsWhenCalled": [ - /// // If you want to mark a function call as side-effect free - /// { "function": "Object.freeze" }, - /// { - /// "module": "react", - /// "functions": ["createContext", "createRef"] - /// }, - /// { - /// "module": "zod", - /// "functions": ["array", "string", "nativeEnum", "number", "object", "optional"] - /// }, - /// { - /// "module": "my/local/module", - /// "functions": ["foo", "bar", "baz"] - /// }, - /// // If you want to whitelist all functions of a module - /// { - /// "module": "lodash", - /// "functions": "*" - /// } - /// ] - /// } - /// ] - /// } - /// } - /// ``` - /// - /// ### Magic Comments - /// - /// Besides the configuration, you can also use magic comments to mark a function call as side effect free. - /// - /// By default, imported functions are assumed to have side-effects, unless they are marked with a magic comment: - /// - /// ```js - /// import { /* tree-shaking no-side-effects-when-called */ x } from "./some-file"; - /// x(); - /// ``` - /// - /// `@__PURE__` is also supported: - /// - /// ```js - /// import {x} from "./some-file"; - /// /*@__PURE__*/ x(); - /// ``` - NoSideEffectsInInitialization, - nursery -); - -impl Rule for NoSideEffectsInInitialization { - fn from_configuration(value: serde_json::Value) -> Self { - let mut functions = vec![]; - let mut modules = vec![]; - - if let Value::Array(arr) = value { - for obj in arr { - let Value::Object(obj) = obj else { - continue; - }; - - // { "function": "Object.freeze" } - if let Some(name) = obj.get("function").and_then(Value::as_str) { - functions.push(name.to_string()); - continue; - } - - // { "module": "react", "functions": ["createContext", "createRef"] } - // { "module": "react", "functions": "*" } - if let Some(name) = obj.get("module").and_then(Value::as_str) { - let functions = match obj.get("functions") { - Some(Value::Array(arr)) => { - let val = arr - .iter() - .filter_map(Value::as_str) - .map(String::from) - .collect::>(); - Some(ModuleFunctions::Specific(val)) - } - Some(Value::String(str)) => { - if str == "*" { - Some(ModuleFunctions::All) - } else { - None - } - } - _ => None, - }; - if let Some(functions) = functions { - modules.push(WhitelistModule { name: name.to_string(), functions }); - } - } - } - } - - Self(Box::new(NoSideEffectsInInitiallizationOptions { functions, modules })) - } - - fn run_once(&self, ctx: &LintContext) { - let Some(root) = ctx.nodes().root_node() else { - return; - }; - let AstKind::Program(program) = root.kind() else { unreachable!() }; - let node_listener_options = NodeListenerOptions::new(ctx) - .with_whitelist_functions(&self.functions) - .with_whitelist_modules(&self.modules); - program.report_effects(&node_listener_options); - } -} - -#[test] -fn test() { - use crate::tester::Tester; - - let pass = vec![ - // ArrayExpression - "[]", - "const x = []", - "const x = [ext,ext]", - "const x = [1,,2,]", - // ArrayPattern - "const [x] = []", - "const [,x,] = []", - // ArrowFunctionExpression - "const x = a=>{a(); ext()}", - // ArrowFunctionExpression when called - "(()=>{})()", - "(a=>{})()", - "((...a)=>{})()", - "(({a})=>{})()", - // ArrowFunctionExpression when mutated - "const x = ()=>{}; x.y = 1", - // AssignmentExpression - "var x;x = {}", - "var x;x += 1", - "const x = {}; x.y = 1", - r#"const x = {}; x["y"] = 1"#, - "function x(){this.y = 1}; const z = new x()", - "let x = 1; x = 2 + 3", - "let x; x = 2 + 3", - // AssignmentPattern - "const {x = ext} = {}", - "const {x: y = ext} = {}", - "const {[ext]: x = ext} = {}", - "const x = ()=>{}, {y = x()} = {}", - // BinaryExpression - "const x = 1 + 2", - "if (1-1) ext()", - // BlockStatement - "{}", - "const x = ()=>{};{const x = ext}x()", - "const x = ext;{const x = ()=>{}; x()}", - // BreakStatement - "while(true){break}", - // CallExpression - "(a=>{const y = a})(ext, ext)", - "const x = ()=>{}, y = ()=>{}; x(y())", - // CatchClause - "try {} catch (error) {}", - "const x = ()=>{}; try {} catch (error) {const x = ext}; x()", - "const x = ext; try {} catch (error) {const x = ()=>{}; x()}", - // ClassBody - "class x {a(){ext()}}", - // ClassBody when called - "class x {a(){ext()}}; const y = new x()", - "class x {constructor(){}}; const y = new x()", - "class y{}; class x extends y{}; const z = new x()", - // ClassDeclaration - "class x extends ext {}", - // ClassDeclaration when called - "class x {}; const y = new x()", - // ClassExpression - "const x = class extends ext {}", - // ClassExpression when called - "const x = new (class {})()", - // ClassProperty - "class x {y}", - "class x {y = 1}", - "class x {y = ext()}", - // ConditionalExpression - "const x = ext ? 1 : 2", - "const x = true ? 1 : ext()", - "const x = false ? ext() : 2", - "if (true ? false : true) ext()", - "ext ? 1 : ext.x", - "ext ? ext.x : 1", - // // ConditionalExpression when called - "const x = ()=>{}, y = ()=>{};(ext ? x : y)()", - "const x = ()=>{}; (true ? x : ext)()", - "const x = ()=>{}; (false ? ext : x)()", - // ContinueStatement - "while(true){continue}", - // DoWhileStatement - "do {} while(true)", - "do {} while(ext > 0)", - "const x = ()=>{}; do x(); while(true)", - // EmptyStatement - ";", - // ExportAllDeclaration - r#"export * from "import""#, - // ExportDefaultDeclaration - "export default ext", - "const x = ext; export default x", - "export default function(){}", - "export default (function(){})", - "const x = function(){}; export default /* tree-shaking no-side-effects-when-called */ x", - "export default /* tree-shaking no-side-effects-when-called */ function(){}", - // ExportNamedDeclaration - "export const x = ext", - "export function x(){ext()}", - "const x = ext; export {x}", - r#"export {x} from "import""#, - r#"export {x as y} from "import""#, - r#"export {x as default} from "import""#, - "export const /* tree-shaking no-side-effects-when-called */ x = function(){}", - "export function /* tree-shaking no-side-effects-when-called */ x(){}", - " - { let x = ext; } - let x = () => {} - export {/* tree-shaking no-side-effects-when-called */ x} - ", - "const x = function(){}; export {/* tree-shaking no-side-effects-when-called */ x}", - // ExpressionStatement - "const x = 1", - // ForInStatement - "for(const x in ext){x = 1}", - "let x; for(x in ext){}", - // ForStatement - "for(let i = 0; i < 3; i++){i++}", - "for(;;){}", - // FunctionDeclaration - "function x(a){a(); ext()}", - // FunctionDeclaration when called - "function x(){}; x()", - "function x(a){}; x()", - "function x(...a){}; x()", - "function x({a}){}; x()", - // FunctionDeclaration when mutated - "function x(){}; x.y = 1", - // FunctionExpression - "const x = function (a){a(); ext()}", - // FunctionExpression when called - "(function (){}())", - "(function (a){}())", - "(function (...a){}())", - "(function ({a}){}())", - // Identifier - "var x;x = 1", - // Identifier when called - "const x = ()=>{};x(ext)", - "function x(){};x(ext)", - "var x = ()=>{};x(ext)", - "const x = ()=>{}, y = ()=>{x()}; y()", - "const x = ext, y = ()=>{const x = ()=>{}; x()}; y()", - // Identifier when mutated - "const x = {}; x.y = ext", - // IfStatement - "let y;if (ext > 0) {y = 1} else {y = 2}", - "if (false) {ext()}", - "if (true) {} else {ext()}", - // ImportDeclaration - r#"import "import""#, - r#"import x from "import-default""#, - r#"import {x} from "import""#, - r#"import {x as y} from "import""#, - r#"import * as x from "import""#, - r#"import /* tree-shaking no-side-effects-when-called */ x from "import-default-no-effects"; x()"#, - r#"import /* test */ /*tree-shaking no-side-effects-when-called */ x from "import-default-no-effects"; x()"#, - // TODO: Current only support the comment next to code. - // r#"import /* tree-shaking no-side-effects-when-called*/ /* test */ x from "import-default-no-effects"; x()"#, - r#"import {/* tree-shaking no-side-effects-when-called */ x} from "import-no-effects"; x()"#, - r#"import {x as /* tree-shaking no-side-effects-when-called */ y} from "import-no-effects"; y()"#, - r#"import {x} from "import"; /*@__PURE__*/ x()"#, - r#"import {x} from "import"; /* @__PURE__ */ x()"#, - // JSXAttribute - r#"class X {}; const x = "#, - "class X {}; const x = ", - "class X {}; const x = />", - // JSXElement - "class X {}; const x = ", - "class X {}; const x = Text", - // JSXEmptyExpression - "class X {}; const x = {}", - // JSXExpressionContainer - "class X {}; const x = {3}", - // JSXIdentifier - "class X {}; const x = ", - "const X = class {constructor() {this.x = 1}}; const x = ", - // JSXOpeningElement - "class X {}; const x = ", - "class X {}; const x = ", - r#"class X {}; const x = "#, - // JSXSpreadAttribute - "class X {}; const x = ", - // LabeledStatement - "loop: for(;true;){continue loop}", - // Literal - "const x = 3", - "if (false) ext()", - r#""use strict""#, - // LogicalExpression - "const x = 3 || 4", - "true || ext()", - "false && ext()", - "if (false && false) ext()", - "if (true && false) ext()", - "if (false && true) ext()", - "if (false || false) ext()", - // MemberExpression - "const x = ext.y", - r#"const x = ext["y"]"#, - "let x = ()=>{}; x.y = 1", - // MemberExpression when called - "const x = Object.keys({})", - // MemberExpression when mutated - "const x = {};x.y = ext", - "const x = {y: 1};delete x.y", - // MetaProperty - "function x(){const y = new.target}; x()", - // MethodDefinition - "class x {a(){}}", - "class x {static a(){}}", - // NewExpression - "const x = new (function (){this.x = 1})()", - "function x(){this.y = 1}; const z = new x()", - "/*@__PURE__*/ new ext()", - // ObjectExpression - "const x = {y: ext}", - r#"const x = {["y"]: ext}"#, - "const x = {};x.y = ext", - // ObjectPattern - "const {x} = {}", - "const {[ext]: x} = {}", - // RestElement - "const [...x] = []", - // ReturnStatement - "(()=>{return})()", - "(()=>{return 1})()", - // SequenceExpression - "let x = 1; x++, x++", - "if (ext, false) ext()", - // SwitchCase - "switch(ext){case ext:const x = 1;break;default:}", - // SwitchStatement - "switch(ext){}", - "const x = ()=>{}; switch(ext){case 1:const x = ext}; x()", - "const x = ext; switch(ext){case 1:const x = ()=>{}; x()}", - // TaggedTemplateExpression - "const x = ()=>{}; const y = x``", - // TemplateLiteral - "const x = ``", - "const x = `Literal`", - "const x = `Literal ${ext}`", - r#"const x = ()=>"a"; const y = `Literal ${x()}`"#, - // ThisExpression - "const y = this.x", - // ThisExpression when mutated - "const y = new (function (){this.x = 1})()", - "const y = new (function (){{this.x = 1}})()", - "const y = new (function (){(()=>{this.x = 1})()})()", - "function x(){this.y = 1}; const y = new x()", - // TryStatement - "try {} catch (error) {}", - "try {} finally {}", - "try {} catch (error) {} finally {}", - // UnaryExpression - "!ext", - "const x = {};delete x.y", - r#"const x = {};delete x["y"]"#, - // UpdateExpression - "let x=1;x++", - "const x = {};x.y++", - // VariableDeclaration - "const x = 1", - // VariableDeclarator - "var x, y", - "var x = 1, y = 2", - "const x = 1, y = 2", - "let x = 1, y = 2", - "const {x} = {}", - // WhileStatement - "while(true){}", - "while(ext > 0){}", - "const x = ()=>{}; while(true)x()", - // YieldExpression - "function* x(){const a = yield}; x()", - "function* x(){yield ext}; x()", - // Supports TypeScript nodes - "interface Blub {}", - " - function a() { - a - } - function b() { - b - } - export { - a, - b - } - ", - " - const Comp = () => { -
- -
- } - ", - ]; - - let fail = vec![ - // ArrayExpression - "const x = [ext()]", - "const x = [,,ext(),]", - // ArrayPattern - "const [x = ext()] = []", - "const [,x = ext(),] = []", - // ArrowFunctionExpression when called - "(()=>{ext()})()", - "(({a = ext()})=>{})()", - "(a=>{a()})(ext)", - "((...a)=>{a()})(ext)", - "(({a})=>{a()})(ext)", - "(a=>{a.x = 1})(ext)", - "(a=>{const b = a;b.x = 1})(ext)", - "((...a)=>{a.x = 1})(ext)", - "(({a})=>{a.x = 1})(ext)", - // AssignmentExpression - "ext = 1", - "ext += 1", - "ext.x = 1", - "const x = {};x[ext()] = 1", - "this.x = 1", - // AssignmentPattern - "const {x = ext()} = {}", - "const {y: {x = ext()} = {}} = {}", - // AwaitExpression - "const x = async ()=>{await ext()}; x()", - // // BinaryExpression - "const x = 1 + ext()", - "const x = ext() + 1", - // BlockStatement - "{ext()}", - // "var x=()=>{};{var x=ext}x()", - "var x=ext;{x(); var x=()=>{}}", - // CallExpression - "(()=>{})(ext(), 1)", - "(()=>{})(1, ext())", - // CallExpression when called - "const x = ()=>ext; const y = x(); y()", - // CallExpression when mutated - "const x = ()=>ext; const y = x(); y.z = 1", - // CatchClause - "try {} catch (error) {ext()}", - // TODO: check global function `ext` call when called `x()` in no strict mode - // "var x=()=>{}; try {} catch (error) {var x=ext}; x()", - // ClassBody - "class x {[ext()](){}}", - // ClassBody when called - "class x {constructor(){ext()}}; new x()", - "class x {constructor(){ext()}}; const y = new x()", - "class x extends ext {}; const y = new x()", - "class y {constructor(){ext()}}; class x extends y {}; const z = new x()", - "class y {constructor(){ext()}}; class x extends y {constructor(){super()}}; const z = new x()", - "class y{}; class x extends y{constructor(){super()}}; const z = new x()", - // ClassDeclaration - "class x extends ext() {}", - "class x {[ext()](){}}", - // ClassDeclaration when called - "class x {constructor(){ext()}}; new x()", - "class x {constructor(){ext()}}; const y = new x()", - "class x extends ext {}; const y = new x()", - // ClassExpression - "const x = class extends ext() {}", - "const x = class {[ext()](){}}", - // ClassExpression when called - "new (class {constructor(){ext()}})()", - "const x = new (class {constructor(){ext()}})()", - "const x = new (class extends ext {})()", - // ClassProperty - "class x {[ext()] = 1}", - // ClassProperty when called - "class x {y = ext()}; new x()", - // ConditionalExpression - "const x = ext() ? 1 : 2", - "const x = ext ? ext() : 2", - "const x = ext ? 1 : ext()", - "if (false ? false : true) ext()", - // ConditionalExpression when called - "const x = ()=>{}; (true ? ext : x)()", - "const x = ()=>{}; (false ? x : ext)()", - "const x = ()=>{}; (ext ? x : ext)()", - // DebuggerStatement - "debugger", - // DoWhileStatement - "do {} while(ext())", - "do ext(); while(true)", - "do {ext()} while(true)", - // ExportDefaultDeclaration - "export default ext()", - "export default /* tree-shaking no-side-effects-when-called */ ext", - "const x = ext; export default /* tree-shaking no-side-effects-when-called */ x", - // ExportNamedDeclaration - "export const x = ext()", - "export const /* tree-shaking no-side-effects-when-called */ x = ext", - "export function /* tree-shaking no-side-effects-when-called */ x(){ext()}", - "const x = ext; export {/* tree-shaking no-side-effects-when-called */ x}", - " - { let x = () => {}; } - let x = ext - export {/* tree-shaking no-side-effects-when-called */ x} - ", - // ExpressionStatement - "ext()", - // ForInStatement - "for(ext in {a: 1}){}", - "for(const x in ext()){}", - "for(const x in {a: 1}){ext()}", - "for(const x in {a: 1}) ext()", - // ForOfStatement - "for(ext of {a: 1}){}", - "for(const x of ext()){}", - "for(const x of {a: 1}){ext()}", - "for(const x of {a: 1}) ext()", - // ForStatement - "for(ext();;){}", - "for(;ext();){}", - "for(;true;ext()){}", - "for(;true;) ext()", - "for(;true;){ext()}", - // FunctionDeclaration when called - "function x(){ext()}; x()", - "function x(){ext()}; const y = new x()", - "function x(){ext()}; new x()", - "function x(a = ext()){}; x()", - "function x(a){a()}; x(ext)", - "function x(...a){a()}; x(ext)", - "function x({a}){a()}; x(ext)", - "function x(a){a(); a(); a()}; x(ext)", - "function x(a){a.y = 1}; x(ext)", - "function x(...a){a.y = 1}; x(ext)", - "function x({a}){a.y = 1}; x(ext)", - "function x(a){a.y = 1; a.y = 2; a.y = 3}; x(ext)", - "function x(){ext = 1}; x(); x(); x()", - "function x(){ext = 1}; const y = new x(); y = new x(); y = new x()", - // FunctionExpression when called - "(function (){ext()}())", - "const x = new (function (){ext()})()", - "new (function (){ext()})()", - "(function ({a = ext()}){}())", - "(function (a){a()}(ext))", - "(function (...a){a()}(ext))", - "(function ({a}){a()}(ext))", - "(function (a){a.x = 1}(ext))", - "(function (a){const b = a;b.x = 1}(ext))", - "(function (...a){a.x = 1}(ext))", - "(function ({a}){a.x = 1}(ext))", - // Identifier when called - "ext()", - "const x = ext; x()", - "let x = ()=>{}; x = ext; x()", - // "var x = ()=>{}; var x = ext; x()", - "const x = ()=>{ext()}; x()", - "const x = ()=>{ext = 1}; x(); x(); x()", - // "let x = ()=>{}; const y = ()=>{x()}; x = ext; y()", - // "var x = ()=>{}; const y = ()=>{x()}; var x = ext; y()", - "const x = ()=>{}; const {y} = x(); y()", - "const x = ()=>{}; const [y] = x(); y()", - // // Identifier when mutated - "var x = ext; x.y = 1", - // "var x = {}; x = ext; x.y = 1", - // "var x = {}; var x = ext; x.y = 1", - // "var x = {}; x = ext; x.y = 1; x.y = 1; x.y = 1", - // "const x = {y:ext}; const {y} = x; y.z = 1", - // IfStatement - "if (ext()>0){}", - "if (1>0){ext()}", - "if (1<0){} else {ext()}", - "if (ext>0){ext()} else {ext()}", - // ImportDeclaration - r#"import x from "import-default"; x()"#, - r#"import x from "import-default"; x.z = 1"#, - r#"import {x} from "import"; x()"#, - r#"import {x} from "import"; x.z = 1"#, - r#"import {x as y} from "import"; y()"#, - r#"import {x as y} from "import"; y.a = 1"#, - r#"import * as y from "import"; y.x()"#, - r#"import * as y from "import"; y.x = 1"#, - // JSXAttribute - "class X {}; const x = ", - "class X {}; class Y {constructor(){ext()}}; const x = />", - // JSXElement - "class X {constructor(){ext()}}; const x = ", - "class X {}; const x = {ext()}", - // JSXExpressionContainer - "class X {}; const x = {ext()}", - // JSXIdentifier - "class X {constructor(){ext()}}; const x = ", - "const X = class {constructor(){ext()}}; const x = ", - "const x = ", - // JSXMemberExpression - "const X = {Y: ext}; const x = ", - // JSXOpeningElement - "class X {}; const x = ", - // JSXSpreadAttribute - "class X {}; const x = ", - // LabeledStatement - "loop: for(;true;){ext()}", - // Literal - "if (true) ext()", - // LogicalExpression - "ext() && true", - "true && ext()", - "false || ext()", - "if (true && true) ext()", - "if (false || true) ext()", - "if (true || false) ext()", - "if (true || true) ext()", - // MemberExpression - "const x = {};const y = x[ext()]", - // MemberExpression when called - "ext.x()", - "const x = {}; x.y()", - "const x = ()=>{}; x().y()", - "const Object = {}; const x = Object.keys({})", - "const x = {}; x[ext()]()", - // MemberExpression when mutated - "const x = {y: ext};x.y.z = 1", - "const x = {y:ext};const y = x.y; y.z = 1", - "const x = {y: ext};delete x.y.z", - // MethodDefinition - "class x {static [ext()](){}}", - // NewExpression - "const x = new ext()", - "new ext()", - // ObjectExpression - "const x = {y: ext()}", - r#"const x = {["y"]: ext()}"#, - "const x = {[ext()]: 1}", - // ObjectPattern - "const {[ext()]: x} = {}", - // ReturnStatement - "(()=>{return ext()})()", - // SequenceExpression - "ext(), 1", - "1, ext()", - "if (1, true) ext()", - "if (1, ext) ext()", - // Super when called - "class y {constructor(){ext()}}; class x extends y {constructor(){super()}}; const z = new x()", - "class y{}; class x extends y{constructor(){super(); super.test()}}; const z = new x()", - "class y{}; class x extends y{constructor(){super()}}; const z = new x()", - // SwitchCase - "switch(ext){case ext():}", - "switch(ext){case 1:ext()}", - // SwitchStatement - "switch(ext()){}", - // "var x=()=>{}; switch(ext){case 1:var x=ext}; x()", - // TaggedTemplateExpression - "const x = ext``", - "ext``", - "const x = ()=>{}; const y = x`${ext()}`", - // TemplateLiteral - "const x = `Literal ${ext()}`", - // ThisExpression when mutated - "this.x = 1", - "(()=>{this.x = 1})()", - "(function(){this.x = 1}())", - "const y = new (function (){(function(){this.x = 1}())})()", - "function x(){this.y = 1}; x()", - // ThrowStatement - r#"throw new Error("Hello Error")"#, - // TryStatement - "try {ext()} catch (error) {}", - "try {} finally {ext()}", - // UnaryExpression - "!ext()", - "delete ext.x", - r#"delete ext["x"]"#, - "const x = ()=>{};delete x()", - // UpdateExpression - "ext++", - "const x = {};x[ext()]++", - // VariableDeclaration - "const x = ext()", - // VariableDeclarator - "var x = ext(),y = ext()", - "const x = ext(),y = ext()", - "let x = ext(),y = ext()", - "const {x = ext()} = {}", - // WhileStatement - "while(ext()){}", - "while(true)ext()", - "while(true){ext()}", - // YieldExpression - "function* x(){yield ext()}; x()", - // YieldExpression when called - "function* x(){yield ext()}; x()", - " - function f() { - try { - f(); - } catch(e) { - a.map(v => v + 1); - } - } - f(); - ", - ]; - - // test options - let pass_with_options = vec![ - ( - "Object.freeze({})", - Some(serde_json::json!([ - { "function": "Object.freeze" }, - ])), - ), - ( - "import {createContext, createRef} from 'react'; createContext(); createRef();", - Some(serde_json::json!([ - { "module": "react", "functions": ["createContext", "createRef"] }, - ])), - ), - ( - "import _ from 'lodash'; _.cloneDeep({});", - Some(serde_json::json!([ - { "module": "lodash", "functions": "*" }, - ])), - ), - ( - "import * as React from 'react'; React.createRef();", - Some(serde_json::json!([ - { "module": "react", "functions": "*" }, - ])), - ), - ]; - - let fail_with_options = vec![ - ("Object.freeze({})", None), - ("import {createContext, createRef} from 'react'; createContext(); createRef();", None), - ("import _ from 'lodash'; _.cloneDeep({});", None), - ("import * as React from 'react'; React.createRef();", None), - ]; - - let pass = - pass.into_iter().map(|case| (case, None)).chain(pass_with_options).collect::>(); - - let fail = - fail.into_iter().map(|case| (case, None)).chain(fail_with_options).collect::>(); - - Tester::new(NoSideEffectsInInitialization::NAME, pass, fail).test_and_snapshot(); -} diff --git a/crates/oxc_linter/src/snapshots/adjacent_overload_signatures.snap b/crates/oxc_linter/src/snapshots/adjacent_overload_signatures.snap index e479260d484b39..1e43b227075dc9 100644 --- a/crates/oxc_linter/src/snapshots/adjacent_overload_signatures.snap +++ b/crates/oxc_linter/src/snapshots/adjacent_overload_signatures.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(adjacent-overload-signatures): All "foo" signatures should be adjacent. ╭─[adjacent_overload_signatures.tsx:3:18] diff --git a/crates/oxc_linter/src/snapshots/alt_text.snap b/crates/oxc_linter/src/snapshots/alt_text.snap index 8abd61a0da3b7b..e577f786936404 100644 --- a/crates/oxc_linter/src/snapshots/alt_text.snap +++ b/crates/oxc_linter/src/snapshots/alt_text.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(alt-text): Missing `alt` attribute. ╭─[alt_text.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/anchor_has_content.snap b/crates/oxc_linter/src/snapshots/anchor_has_content.snap index 1b95f380f53cf9..11e218fa7169b3 100644 --- a/crates/oxc_linter/src/snapshots/anchor_has_content.snap +++ b/crates/oxc_linter/src/snapshots/anchor_has_content.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(anchor-has-content): Missing accessible content when using `a` elements. ╭─[anchor_has_content.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/anchor_is_valid.snap b/crates/oxc_linter/src/snapshots/anchor_is_valid.snap index 2eb831732ff805..360e07ff3961d4 100644 --- a/crates/oxc_linter/src/snapshots/anchor_is_valid.snap +++ b/crates/oxc_linter/src/snapshots/anchor_is_valid.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(anchor-is-valid): Missing `href` attribute for the `a` element. ╭─[anchor_is_valid.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/api_keys@aws_access_token.snap b/crates/oxc_linter/src/snapshots/api_keys@aws_access_token.snap index 099f8cfbc8353e..65c9da5091aa72 100644 --- a/crates/oxc_linter/src/snapshots/api_keys@aws_access_token.snap +++ b/crates/oxc_linter/src/snapshots/api_keys@aws_access_token.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc-security(api-keys/aws-access-token): Detected an AWS Access Key ID, which may lead to unauthorized access to AWS resources. ╭─[api_keys.tsx:1:11] diff --git a/crates/oxc_linter/src/snapshots/approx_constant.snap b/crates/oxc_linter/src/snapshots/approx_constant.snap index a445efde94f519..9b6675d836b810 100644 --- a/crates/oxc_linter/src/snapshots/approx_constant.snap +++ b/crates/oxc_linter/src/snapshots/approx_constant.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(approx-constant): Approximate value of `PI` found. ╭─[approx_constant.tsx:1:29] diff --git a/crates/oxc_linter/src/snapshots/aria_activedescendant_has_tabindex.snap b/crates/oxc_linter/src/snapshots/aria_activedescendant_has_tabindex.snap index 2a2e9f693ee826..8663b2625a4be1 100644 --- a/crates/oxc_linter/src/snapshots/aria_activedescendant_has_tabindex.snap +++ b/crates/oxc_linter/src/snapshots/aria_activedescendant_has_tabindex.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(aria-activedescendant-has-tabindex): Elements with `aria-activedescendant` must be tabbable. ╭─[aria_activedescendant_has_tabindex.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/aria_props.snap b/crates/oxc_linter/src/snapshots/aria_props.snap index 2b7a97035c20f2..9d0317bcd35a33 100644 --- a/crates/oxc_linter/src/snapshots/aria_props.snap +++ b/crates/oxc_linter/src/snapshots/aria_props.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(aria-props): 'aria-' is not a valid ARIA attribute. ╭─[aria_props.tsx:1:6] diff --git a/crates/oxc_linter/src/snapshots/aria_role.snap b/crates/oxc_linter/src/snapshots/aria_role.snap index d107ef9f5990e6..c1c33d5dcea500 100644 --- a/crates/oxc_linter/src/snapshots/aria_role.snap +++ b/crates/oxc_linter/src/snapshots/aria_role.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(aria-role): Elements with ARIA roles must use a valid, non-abstract ARIA role. ╭─[aria_role.tsx:1:11] diff --git a/crates/oxc_linter/src/snapshots/aria_unsupported_elements.snap b/crates/oxc_linter/src/snapshots/aria_unsupported_elements.snap index 9fd930a8a40614..97c79c7a285e88 100644 --- a/crates/oxc_linter/src/snapshots/aria_unsupported_elements.snap +++ b/crates/oxc_linter/src/snapshots/aria_unsupported_elements.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(aria-unsupported-elements): This element does not support ARIA roles, states and properties. ╭─[aria_unsupported_elements.tsx:1:7] diff --git a/crates/oxc_linter/src/snapshots/array_callback_return.snap b/crates/oxc_linter/src/snapshots/array_callback_return.snap index 6d2c209de3e9fd..9c70c9abb14087 100644 --- a/crates/oxc_linter/src/snapshots/array_callback_return.snap +++ b/crates/oxc_linter/src/snapshots/array_callback_return.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(array-callback-return): Missing return on some path for array method "Array.from" ╭─[array_callback_return.tsx:1:26] diff --git a/crates/oxc_linter/src/snapshots/array_type.snap b/crates/oxc_linter/src/snapshots/array_type.snap index 13be26fb6c1f61..c4fec3865f49d8 100644 --- a/crates/oxc_linter/src/snapshots/array_type.snap +++ b/crates/oxc_linter/src/snapshots/array_type.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(array-type): Array type using 'Array' is forbidden. Use 'number[]' instead. ╭─[array_type.tsx:1:8] diff --git a/crates/oxc_linter/src/snapshots/autocomplete_valid.snap b/crates/oxc_linter/src/snapshots/autocomplete_valid.snap index 57c5204304a465..66cd850e8a0023 100644 --- a/crates/oxc_linter/src/snapshots/autocomplete_valid.snap +++ b/crates/oxc_linter/src/snapshots/autocomplete_valid.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(autocomplete-valid): `foo` is not a valid value for autocomplete. ╭─[autocomplete_valid.tsx:1:20] diff --git a/crates/oxc_linter/src/snapshots/avoid_new.snap b/crates/oxc_linter/src/snapshots/avoid_new.snap index d023f7b19141d9..a84e8cd3ec6bf6 100644 --- a/crates/oxc_linter/src/snapshots/avoid_new.snap +++ b/crates/oxc_linter/src/snapshots/avoid_new.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-promise(avoid-new): Avoid creating new promises ╭─[avoid_new.tsx:1:9] diff --git a/crates/oxc_linter/src/snapshots/bad_array_method_on_arguments.snap b/crates/oxc_linter/src/snapshots/bad_array_method_on_arguments.snap index e028d76fc91ef6..df0f80c6bcf380 100644 --- a/crates/oxc_linter/src/snapshots/bad_array_method_on_arguments.snap +++ b/crates/oxc_linter/src/snapshots/bad_array_method_on_arguments.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-array-method-on-arguments): Bad array method on arguments ╭─[bad_array_method_on_arguments.tsx:1:16] diff --git a/crates/oxc_linter/src/snapshots/bad_bitwise_operator.snap b/crates/oxc_linter/src/snapshots/bad_bitwise_operator.snap index e7f5ec0fd2306f..c1dc5522cf656f 100644 --- a/crates/oxc_linter/src/snapshots/bad_bitwise_operator.snap +++ b/crates/oxc_linter/src/snapshots/bad_bitwise_operator.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-bitwise-operator): Bad bitwise operator ╭─[bad_bitwise_operator.tsx:1:9] diff --git a/crates/oxc_linter/src/snapshots/bad_char_at_comparison.snap b/crates/oxc_linter/src/snapshots/bad_char_at_comparison.snap index 50b0e2e794beaa..8d747338313dc3 100644 --- a/crates/oxc_linter/src/snapshots/bad_char_at_comparison.snap +++ b/crates/oxc_linter/src/snapshots/bad_char_at_comparison.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-char-at-comparison): Invalid comparison with `charAt` method ╭─[bad_char_at_comparison.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/bad_comparison_sequence.snap b/crates/oxc_linter/src/snapshots/bad_comparison_sequence.snap index 7b1097b4d4ad79..b08afd5b1b1aa0 100644 --- a/crates/oxc_linter/src/snapshots/bad_comparison_sequence.snap +++ b/crates/oxc_linter/src/snapshots/bad_comparison_sequence.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-comparison-sequence): Bad comparison sequence ╭─[bad_comparison_sequence.tsx:1:5] diff --git a/crates/oxc_linter/src/snapshots/bad_min_max_func.snap b/crates/oxc_linter/src/snapshots/bad_min_max_func.snap index 2ac4bf34cdeb81..94fc63ff1356f1 100644 --- a/crates/oxc_linter/src/snapshots/bad_min_max_func.snap +++ b/crates/oxc_linter/src/snapshots/bad_min_max_func.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-min-max-func): Math.min and Math.max combination leads to constant result ╭─[bad_min_max_func.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/bad_object_literal_comparison.snap b/crates/oxc_linter/src/snapshots/bad_object_literal_comparison.snap index 0a97b36c0523c5..32fb8def65849b 100644 --- a/crates/oxc_linter/src/snapshots/bad_object_literal_comparison.snap +++ b/crates/oxc_linter/src/snapshots/bad_object_literal_comparison.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-object-literal-comparison): Unexpected object literal comparison. ╭─[bad_object_literal_comparison.tsx:1:5] diff --git a/crates/oxc_linter/src/snapshots/bad_replace_all_arg.snap b/crates/oxc_linter/src/snapshots/bad_replace_all_arg.snap index acd18e36c06eda..255783a83e3503 100644 --- a/crates/oxc_linter/src/snapshots/bad_replace_all_arg.snap +++ b/crates/oxc_linter/src/snapshots/bad_replace_all_arg.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(bad-replace-all-arg): Global flag (g) is missing in the regular expression supplied to the `replaceAll` method. ╭─[bad_replace_all_arg.tsx:1:12] diff --git a/crates/oxc_linter/src/snapshots/ban_ts_comment.snap b/crates/oxc_linter/src/snapshots/ban_ts_comment.snap index db4d8272c03e65..03269d05e8e186 100644 --- a/crates/oxc_linter/src/snapshots/ban_ts_comment.snap +++ b/crates/oxc_linter/src/snapshots/ban_ts_comment.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(ban-ts-comment): Do not use @ts-expect-error because it alters compilation errors. ╭─[ban_ts_comment.tsx:1:3] diff --git a/crates/oxc_linter/src/snapshots/ban_tslint_comment.snap b/crates/oxc_linter/src/snapshots/ban_tslint_comment.snap index a0f87008fe8260..e2b56bbd6d84dc 100644 --- a/crates/oxc_linter/src/snapshots/ban_tslint_comment.snap +++ b/crates/oxc_linter/src/snapshots/ban_tslint_comment.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(ban-tslint-comment): tslint comment detected: "tslint:disable" ╭─[ban_tslint_comment.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/ban_types.snap b/crates/oxc_linter/src/snapshots/ban_types.snap index 241168cb006a69..04124ce7af496d 100644 --- a/crates/oxc_linter/src/snapshots/ban_types.snap +++ b/crates/oxc_linter/src/snapshots/ban_types.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(ban-types): Do not use "String" as a type. Use "string" instead ╭─[ban_types.tsx:1:8] diff --git a/crates/oxc_linter/src/snapshots/button_has_type.snap b/crates/oxc_linter/src/snapshots/button_has_type.snap index a42f06e32ab1a3..84e35b62a4aca3 100644 --- a/crates/oxc_linter/src/snapshots/button_has_type.snap +++ b/crates/oxc_linter/src/snapshots/button_has_type.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(button-has-type): `button` elements must have an explicit `type` attribute. ╭─[button_has_type.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/catch_error_name.snap b/crates/oxc_linter/src/snapshots/catch_error_name.snap index 8d20046cae3723..8ae65a0df49208 100644 --- a/crates/oxc_linter/src/snapshots/catch_error_name.snap +++ b/crates/oxc_linter/src/snapshots/catch_error_name.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(catch-error-name): The catch parameter "descriptiveError" should be named "exception" ╭─[catch_error_name.tsx:1:16] diff --git a/crates/oxc_linter/src/snapshots/catch_or_return.snap b/crates/oxc_linter/src/snapshots/catch_or_return.snap index 279b77ebe38136..99fb2191895b7a 100644 --- a/crates/oxc_linter/src/snapshots/catch_or_return.snap +++ b/crates/oxc_linter/src/snapshots/catch_or_return.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-promise(catch-or-return): eslint-plugin-promise(catch-or-return): Expected catch or return ╭─[catch_or_return.tsx:1:37] diff --git a/crates/oxc_linter/src/snapshots/check_access.snap b/crates/oxc_linter/src/snapshots/check_access.snap index 3dfb116c11ed09..eee127a65aac6c 100644 --- a/crates/oxc_linter/src/snapshots/check_access.snap +++ b/crates/oxc_linter/src/snapshots/check_access.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsdoc(check-access): Invalid access level is specified or missing. ╭─[check_access.tsx:3:25] diff --git a/crates/oxc_linter/src/snapshots/check_property_names.snap b/crates/oxc_linter/src/snapshots/check_property_names.snap index 3feab86da4fd3a..ff2b2043374a3e 100644 --- a/crates/oxc_linter/src/snapshots/check_property_names.snap +++ b/crates/oxc_linter/src/snapshots/check_property_names.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsdoc(check-property-names): No root defined for @property path. ╭─[check_property_names.tsx:4:27] diff --git a/crates/oxc_linter/src/snapshots/check_tag_names.snap b/crates/oxc_linter/src/snapshots/check_tag_names.snap index 230be91090cbb7..c0a668ca18a004 100644 --- a/crates/oxc_linter/src/snapshots/check_tag_names.snap +++ b/crates/oxc_linter/src/snapshots/check_tag_names.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsdoc(check-tag-names): Invalid tag name found. ╭─[check_tag_names.tsx:2:24] diff --git a/crates/oxc_linter/src/snapshots/checked_requires_onchange_or_readonly.snap b/crates/oxc_linter/src/snapshots/checked_requires_onchange_or_readonly.snap index 9e4284fd0d9502..2205f0abaf707a 100644 --- a/crates/oxc_linter/src/snapshots/checked_requires_onchange_or_readonly.snap +++ b/crates/oxc_linter/src/snapshots/checked_requires_onchange_or_readonly.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(checked-requires-onchange-or-readonly): `checked` should be used with either `onChange` or `readOnly`. ╭─[checked_requires_onchange_or_readonly.tsx:1:21] diff --git a/crates/oxc_linter/src/snapshots/click_events_have_key_events.snap b/crates/oxc_linter/src/snapshots/click_events_have_key_events.snap index cafa8776febf44..9d02284a18bcc6 100644 --- a/crates/oxc_linter/src/snapshots/click_events_have_key_events.snap +++ b/crates/oxc_linter/src/snapshots/click_events_have_key_events.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(click-events-have-key-events): Enforce a clickable non-interactive element has at least one keyboard event listener. ╭─[click_events_have_key_events.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/consistent_empty_array_spread.snap b/crates/oxc_linter/src/snapshots/consistent_empty_array_spread.snap index c9895f9863cc43..664933dec4b515 100644 --- a/crates/oxc_linter/src/snapshots/consistent_empty_array_spread.snap +++ b/crates/oxc_linter/src/snapshots/consistent_empty_array_spread.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(consistent-empty-array-spread): Prefer consistent types when spreading a ternary in an array literal. ╭─[consistent_empty_array_spread.tsx:1:24] diff --git a/crates/oxc_linter/src/snapshots/consistent_function_scoping.snap b/crates/oxc_linter/src/snapshots/consistent_function_scoping.snap index c449ccf26bb062..50b5406e329376 100644 --- a/crates/oxc_linter/src/snapshots/consistent_function_scoping.snap +++ b/crates/oxc_linter/src/snapshots/consistent_function_scoping.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(consistent-function-scoping): Function does not capture any variables from the outer scope. ╭─[consistent_function_scoping.tsx:3:30] diff --git a/crates/oxc_linter/src/snapshots/consistent_indexed_object_style.snap b/crates/oxc_linter/src/snapshots/consistent_indexed_object_style.snap index ff5ce7b7ae11ec..f33ef8da85354a 100644 --- a/crates/oxc_linter/src/snapshots/consistent_indexed_object_style.snap +++ b/crates/oxc_linter/src/snapshots/consistent_indexed_object_style.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(consistent-indexed-object-style): A record is preferred over an index signature. ╭─[consistent_indexed_object_style.tsx:3:12] diff --git a/crates/oxc_linter/src/snapshots/consistent_test_it.snap b/crates/oxc_linter/src/snapshots/consistent_test_it.snap index 1a71f34cdbe6da..8b05ea5c841b91 100644 --- a/crates/oxc_linter/src/snapshots/consistent_test_it.snap +++ b/crates/oxc_linter/src/snapshots/consistent_test_it.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-vitest(consistent-test-it): Enforce `test` and `it` usage conventions ╭─[consistent_test_it.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/consistent_type_definitions.snap b/crates/oxc_linter/src/snapshots/consistent_type_definitions.snap index caf9a49362022c..5f6cf6ab08e97a 100644 --- a/crates/oxc_linter/src/snapshots/consistent_type_definitions.snap +++ b/crates/oxc_linter/src/snapshots/consistent_type_definitions.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(consistent-type-definitions): Use an `interface` instead of a `type` ╭─[consistent_type_definitions.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/consistent_type_imports.snap b/crates/oxc_linter/src/snapshots/consistent_type_imports.snap index d3333cd4f9d8b2..bed9424ce5ba94 100644 --- a/crates/oxc_linter/src/snapshots/consistent_type_imports.snap +++ b/crates/oxc_linter/src/snapshots/consistent_type_imports.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(consistent-type-imports): All imports in the declaration are only used as types. Use `import type`. ╭─[consistent_type_imports.tsx:2:15] diff --git a/crates/oxc_linter/src/snapshots/const_comparisons.snap b/crates/oxc_linter/src/snapshots/const_comparisons.snap index c392521e2a7006..0a2c19fcd1fc9c 100644 --- a/crates/oxc_linter/src/snapshots/const_comparisons.snap +++ b/crates/oxc_linter/src/snapshots/const_comparisons.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(const-comparisons): Unexpected constant comparison ╭─[const_comparisons.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/constructor_super.snap b/crates/oxc_linter/src/snapshots/constructor_super.snap index 2adf1447d2f846..03f218bf6f1cbf 100644 --- a/crates/oxc_linter/src/snapshots/constructor_super.snap +++ b/crates/oxc_linter/src/snapshots/constructor_super.snap @@ -1,4 +1,5 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- diff --git a/crates/oxc_linter/src/snapshots/default.snap b/crates/oxc_linter/src/snapshots/default.snap index b85cc3452c5974..ee9154a502a846 100644 --- a/crates/oxc_linter/src/snapshots/default.snap +++ b/crates/oxc_linter/src/snapshots/default.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-import(default): No default export found in imported module "./named-exports" ╭─[index.js:1:8] diff --git a/crates/oxc_linter/src/snapshots/default_case.snap b/crates/oxc_linter/src/snapshots/default_case.snap index 6144661844a547..0f3c5143449e13 100644 --- a/crates/oxc_linter/src/snapshots/default_case.snap +++ b/crates/oxc_linter/src/snapshots/default_case.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(default-case): Require default cases in switch statements. ╭─[default_case.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/default_case_last.snap b/crates/oxc_linter/src/snapshots/default_case_last.snap index cb2665ea19f620..1e991b83dc88f3 100644 --- a/crates/oxc_linter/src/snapshots/default_case_last.snap +++ b/crates/oxc_linter/src/snapshots/default_case_last.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(default-case-last): Enforce default clauses in switch statements to be last ╭─[default_case_last.tsx:1:16] diff --git a/crates/oxc_linter/src/snapshots/default_param_last.snap b/crates/oxc_linter/src/snapshots/default_param_last.snap index 238a8dbec65d15..c0cd80f8183dd3 100644 --- a/crates/oxc_linter/src/snapshots/default_param_last.snap +++ b/crates/oxc_linter/src/snapshots/default_param_last.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(default-param-last): Default parameters should be last ╭─[default_param_last.tsx:1:12] diff --git a/crates/oxc_linter/src/snapshots/double_comparisons.snap b/crates/oxc_linter/src/snapshots/double_comparisons.snap index 237b72f92c3f52..061094be4d11d7 100644 --- a/crates/oxc_linter/src/snapshots/double_comparisons.snap +++ b/crates/oxc_linter/src/snapshots/double_comparisons.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(double-comparisons): Unexpected double comparisons. ╭─[double_comparisons.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/empty_brace_spaces.snap b/crates/oxc_linter/src/snapshots/empty_brace_spaces.snap index c17528fcbfc005..3717b95fa29f60 100644 --- a/crates/oxc_linter/src/snapshots/empty_brace_spaces.snap +++ b/crates/oxc_linter/src/snapshots/empty_brace_spaces.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(empty-brace-spaces): No spaces inside empty pair of braces allowed ╭─[empty_brace_spaces.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/empty_tags.snap b/crates/oxc_linter/src/snapshots/empty_tags.snap index 95966dd47223c2..f573002336a8e7 100644 --- a/crates/oxc_linter/src/snapshots/empty_tags.snap +++ b/crates/oxc_linter/src/snapshots/empty_tags.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsdoc(empty-tags): Expects the void tags to be empty of any content. ╭─[empty_tags.tsx:3:27] diff --git a/crates/oxc_linter/src/snapshots/eqeqeq.snap b/crates/oxc_linter/src/snapshots/eqeqeq.snap index 5c9da273e62518..7bd4eb8cf98d37 100644 --- a/crates/oxc_linter/src/snapshots/eqeqeq.snap +++ b/crates/oxc_linter/src/snapshots/eqeqeq.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(eqeqeq): Expected > and instead saw >= ╭─[eqeqeq.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/erasing_op.snap b/crates/oxc_linter/src/snapshots/erasing_op.snap index 553cff506667b5..daa994246381c7 100644 --- a/crates/oxc_linter/src/snapshots/erasing_op.snap +++ b/crates/oxc_linter/src/snapshots/erasing_op.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ oxc(erasing-op): Unexpected erasing operation. This expression will always evaluate to zero. ╭─[erasing_op.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/error_message.snap b/crates/oxc_linter/src/snapshots/error_message.snap index abed373adc43b2..a73a63e911562d 100644 --- a/crates/oxc_linter/src/snapshots/error_message.snap +++ b/crates/oxc_linter/src/snapshots/error_message.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(error-message): Pass a message to the Error constructor. ╭─[error_message.tsx:1:7] diff --git a/crates/oxc_linter/src/snapshots/escape_case.snap b/crates/oxc_linter/src/snapshots/escape_case.snap index 2d57ac5467eb42..34a4aae059ee2e 100644 --- a/crates/oxc_linter/src/snapshots/escape_case.snap +++ b/crates/oxc_linter/src/snapshots/escape_case.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(escape-case): Use uppercase characters for the value of the escape sequence. ╭─[escape_case.tsx:1:13] diff --git a/crates/oxc_linter/src/snapshots/exhaustive_deps.snap b/crates/oxc_linter/src/snapshots/exhaustive_deps.snap index 12bc5b2b3644d1..6be9889e18f36f 100644 --- a/crates/oxc_linter/src/snapshots/exhaustive_deps.snap +++ b/crates/oxc_linter/src/snapshots/exhaustive_deps.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react-hooks(exhaustive-deps): React Hook useCallback has a missing dependency: 'props.foo.toString' ╭─[exhaustive_deps.tsx:4:14] diff --git a/crates/oxc_linter/src/snapshots/expect_expect.snap b/crates/oxc_linter/src/snapshots/expect_expect.snap index 9546945ba3e3a8..0d55db374536dc 100644 --- a/crates/oxc_linter/src/snapshots/expect_expect.snap +++ b/crates/oxc_linter/src/snapshots/expect_expect.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-vitest(expect-expect): Test has no assertions ╭─[expect_expect.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/explicit_function_return_type.snap b/crates/oxc_linter/src/snapshots/explicit_function_return_type.snap index 8db941e370cc4e..ed17312b109dc7 100644 --- a/crates/oxc_linter/src/snapshots/explicit_function_return_type.snap +++ b/crates/oxc_linter/src/snapshots/explicit_function_return_type.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ typescript-eslint(explicit-function-return-type): Missing return type on function. ╭─[explicit_function_return_type.tsx:2:10] diff --git a/crates/oxc_linter/src/snapshots/explicit_length_check.snap b/crates/oxc_linter/src/snapshots/explicit_length_check.snap index e3fb1306b7791a..47636f49ed6e66 100644 --- a/crates/oxc_linter/src/snapshots/explicit_length_check.snap +++ b/crates/oxc_linter/src/snapshots/explicit_length_check.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(explicit-length-check): Use `.length > 0` when checking length is not zero. ╭─[explicit_length_check.tsx:1:11] diff --git a/crates/oxc_linter/src/snapshots/export.snap b/crates/oxc_linter/src/snapshots/export.snap index ab121c635b966e..6df1bdc54aa423 100644 --- a/crates/oxc_linter/src/snapshots/export.snap +++ b/crates/oxc_linter/src/snapshots/export.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-import(export): Multiple exports of name 'foo'. ╭─[index.ts:1:19] diff --git a/crates/oxc_linter/src/snapshots/filename_case.snap b/crates/oxc_linter/src/snapshots/filename_case.snap index 283b383a9096bc..f878e421f06c9f 100644 --- a/crates/oxc_linter/src/snapshots/filename_case.snap +++ b/crates/oxc_linter/src/snapshots/filename_case.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-unicorn(filename-case): Filename should be in kebab case ╭─[filename_case.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/first.snap b/crates/oxc_linter/src/snapshots/first.snap index 3b0cc6fed1a6b8..3c53ebe2ff3026 100644 --- a/crates/oxc_linter/src/snapshots/first.snap +++ b/crates/oxc_linter/src/snapshots/first.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-import(first): Import statements must come first ╭─[index.ts:3:15] diff --git a/crates/oxc_linter/src/snapshots/for_direction.snap b/crates/oxc_linter/src/snapshots/for_direction.snap index 3daf0e7b89930a..ae6a3a2a100b04 100644 --- a/crates/oxc_linter/src/snapshots/for_direction.snap +++ b/crates/oxc_linter/src/snapshots/for_direction.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(for-direction): The update clause in this loop moves the variable in the wrong direction ╭─[for_direction.tsx:1:17] diff --git a/crates/oxc_linter/src/snapshots/func_names.snap b/crates/oxc_linter/src/snapshots/func_names.snap index 74310779408957..346c0e52aab570 100644 --- a/crates/oxc_linter/src/snapshots/func_names.snap +++ b/crates/oxc_linter/src/snapshots/func_names.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(func-names): Unexpected unnamed function. ╭─[func_names.tsx:1:21] diff --git a/crates/oxc_linter/src/snapshots/getter_return.snap b/crates/oxc_linter/src/snapshots/getter_return.snap index 088647bfad4a6d..b290f39a4ae254 100644 --- a/crates/oxc_linter/src/snapshots/getter_return.snap +++ b/crates/oxc_linter/src/snapshots/getter_return.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(getter-return): Expected to always return a value in getter. ╭─[getter_return.js:1:20] diff --git a/crates/oxc_linter/src/snapshots/google_font_display.snap b/crates/oxc_linter/src/snapshots/google_font_display.snap index 503e15679202cc..8014f7b968292e 100644 --- a/crates/oxc_linter/src/snapshots/google_font_display.snap +++ b/crates/oxc_linter/src/snapshots/google_font_display.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-next(google-font-display): A font-display parameter is missing (adding `&display=optional` is recommended). ╭─[google_font_display.tsx:6:7] diff --git a/crates/oxc_linter/src/snapshots/google_font_preconnect.snap b/crates/oxc_linter/src/snapshots/google_font_preconnect.snap index 4d2179090b4dd7..de31bb1b3f35dd 100644 --- a/crates/oxc_linter/src/snapshots/google_font_preconnect.snap +++ b/crates/oxc_linter/src/snapshots/google_font_preconnect.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-next(google-font-preconnect): `rel="preconnect"` is missing from Google Font. ╭─[google_font_preconnect.tsx:4:15] diff --git a/crates/oxc_linter/src/snapshots/guard_for_in.snap b/crates/oxc_linter/src/snapshots/guard_for_in.snap index e8d1a0a92fbb5f..7180608298e4aa 100644 --- a/crates/oxc_linter/src/snapshots/guard_for_in.snap +++ b/crates/oxc_linter/src/snapshots/guard_for_in.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(guard-for-in): Require `for-in` loops to include an `if` statement ╭─[guard_for_in.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/heading_has_content.snap b/crates/oxc_linter/src/snapshots/heading_has_content.snap index b963e03a91066c..d27ecd7d878e9d 100644 --- a/crates/oxc_linter/src/snapshots/heading_has_content.snap +++ b/crates/oxc_linter/src/snapshots/heading_has_content.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(heading-has-content): Headings must have content and the content must be accessible by a screen reader. ╭─[heading_has_content.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/html_has_lang.snap b/crates/oxc_linter/src/snapshots/html_has_lang.snap index 2337ea66fe8e14..c5a60e5f83ab7d 100644 --- a/crates/oxc_linter/src/snapshots/html_has_lang.snap +++ b/crates/oxc_linter/src/snapshots/html_has_lang.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(html-has-lang): Missing lang attribute. ╭─[html_has_lang.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/iframe_has_title.snap b/crates/oxc_linter/src/snapshots/iframe_has_title.snap index 652503ce7b7da0..487208f9e1d82f 100644 --- a/crates/oxc_linter/src/snapshots/iframe_has_title.snap +++ b/crates/oxc_linter/src/snapshots/iframe_has_title.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(iframe-has-title): Missing `title` attribute for the `iframe` element. ╭─[iframe_has_title.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/iframe_missing_sandbox.snap b/crates/oxc_linter/src/snapshots/iframe_missing_sandbox.snap index 5020fd10abae07..f414c95a88a8ea 100644 --- a/crates/oxc_linter/src/snapshots/iframe_missing_sandbox.snap +++ b/crates/oxc_linter/src/snapshots/iframe_missing_sandbox.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(iframe-missing-sandbox): An iframe element is missing a sandbox attribute ╭─[iframe_missing_sandbox.tsx:1:2] diff --git a/crates/oxc_linter/src/snapshots/img_redundant_alt.snap b/crates/oxc_linter/src/snapshots/img_redundant_alt.snap index bdbc7736b21a26..a58f65cdd83272 100644 --- a/crates/oxc_linter/src/snapshots/img_redundant_alt.snap +++ b/crates/oxc_linter/src/snapshots/img_redundant_alt.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(img-redundant-alt): Redundant alt attribute. ╭─[img_redundant_alt.tsx:1:6] diff --git a/crates/oxc_linter/src/snapshots/implements_on_classes.snap b/crates/oxc_linter/src/snapshots/implements_on_classes.snap index 77a2cbf0a1345b..147c1f099f89be 100644 --- a/crates/oxc_linter/src/snapshots/implements_on_classes.snap +++ b/crates/oxc_linter/src/snapshots/implements_on_classes.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsdoc(implements-on-classes): `@implements` used on a non-constructor function ╭─[implements_on_classes.tsx:3:13] diff --git a/crates/oxc_linter/src/snapshots/import_no_namespace.snap b/crates/oxc_linter/src/snapshots/import_no_namespace.snap index af3286c6777177..e14e1a57c37e4e 100644 --- a/crates/oxc_linter/src/snapshots/import_no_namespace.snap +++ b/crates/oxc_linter/src/snapshots/import_no_namespace.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-import(import-no-namespace): Usage of namespaced aka wildcard "*" imports prohibited ╭─[index.js:1:13] diff --git a/crates/oxc_linter/src/snapshots/inline_script_id.snap b/crates/oxc_linter/src/snapshots/inline_script_id.snap index 357b786421f82f..e4b6e3a0448368 100644 --- a/crates/oxc_linter/src/snapshots/inline_script_id.snap +++ b/crates/oxc_linter/src/snapshots/inline_script_id.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-next(inline-script-id): `next/script` components with inline content must specify an `id` attribute. ╭─[inline_script_id.tsx:5:17] diff --git a/crates/oxc_linter/src/snapshots/jsx_boolean_value.snap b/crates/oxc_linter/src/snapshots/jsx_boolean_value.snap index 46bf714d8bfead..bf8a2dfc797698 100644 --- a/crates/oxc_linter/src/snapshots/jsx_boolean_value.snap +++ b/crates/oxc_linter/src/snapshots/jsx_boolean_value.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-boolean-value): Value must be omitted for boolean attribute "foo" ╭─[jsx_boolean_value.tsx:1:9] diff --git a/crates/oxc_linter/src/snapshots/jsx_curly_brace_presence.snap b/crates/oxc_linter/src/snapshots/jsx_curly_brace_presence.snap index 9d38b5b3e28569..b940ef90a1cd3a 100644 --- a/crates/oxc_linter/src/snapshots/jsx_curly_brace_presence.snap +++ b/crates/oxc_linter/src/snapshots/jsx_curly_brace_presence.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-curly-brace-presence): Curly braces are unnecessary here. ╭─[jsx_curly_brace_presence.tsx:1:12] diff --git a/crates/oxc_linter/src/snapshots/jsx_key.snap b/crates/oxc_linter/src/snapshots/jsx_key.snap index 62f40cb899dca1..e991b8c1c8a95c 100644 --- a/crates/oxc_linter/src/snapshots/jsx_key.snap +++ b/crates/oxc_linter/src/snapshots/jsx_key.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-key): Missing "key" prop for element in array. ╭─[jsx_key.tsx:1:3] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap b/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap index 6ffab885065553..8eb2797c87478e 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_comment_textnodes.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-no-comment-textnodes): Comments inside children section of tag should be placed inside braces ╭─[jsx_no_comment_textnodes.tsx:4:29] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_duplicate_props.snap b/crates/oxc_linter/src/snapshots/jsx_no_duplicate_props.snap index a4e1417ac8098e..a6ccdc1294d844 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_duplicate_props.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_duplicate_props.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-no-duplicate-props): No duplicate props allowed. The prop "a" is duplicated. ╭─[jsx_no_duplicate_props.tsx:1:6] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap index 7f25083157cea8..7398e3a45e0046 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_jsx_as_prop.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react-perf(jsx-no-jsx-as-prop): JSX attribute values should not contain other JSX. ╭─[jsx_no_jsx_as_prop.tsx:1:31] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap index 3841422ccfb52d..08d263bf240d22 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_array_as_prop.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react-perf(jsx-no-new-array-as-prop): JSX attribute values should not contain Arrays created in the same scope. ╭─[jsx_no_new_array_as_prop.tsx:1:32] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap index 7ad4ce70427030..8ca86c7fa9aa4b 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_function_as_prop.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react-perf(jsx-no-new-function-as-prop): JSX attribute values should not contain functions created in the same scope. ╭─[jsx_no_new_function_as_prop.tsx:1:32] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap b/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap index cbfe2e3f935b69..81b73ce70284b2 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_new_object_as_prop.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react-perf(jsx-no-new-object-as-prop): JSX attribute values should not contain objects created in the same scope. ╭─[jsx_no_new_object_as_prop.tsx:1:33] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_target_blank.snap b/crates/oxc_linter/src/snapshots/jsx_no_target_blank.snap index 1ddef52dc80242..fe76d9cedc35b3 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_target_blank.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_target_blank.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-no-target-blank): Using target=`_blank` without rel=`noreferrer` (which implies rel=`noopener`) is a security risk in older browsers: see https://mathiasbynens.github.io/rel-noopener/#recommendations ╭─[jsx_no_target_blank.tsx:1:11] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_undef.snap b/crates/oxc_linter/src/snapshots/jsx_no_undef.snap index 35bff1978aac6b..5ac8fd34a17f0f 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_undef.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_undef.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-no-undef): 'App' is not defined. ╭─[jsx_no_undef.tsx:1:26] diff --git a/crates/oxc_linter/src/snapshots/jsx_no_useless_fragment.snap b/crates/oxc_linter/src/snapshots/jsx_no_useless_fragment.snap index e3c2166139d0fe..e2cc4df814c25f 100644 --- a/crates/oxc_linter/src/snapshots/jsx_no_useless_fragment.snap +++ b/crates/oxc_linter/src/snapshots/jsx_no_useless_fragment.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-no-useless-fragment): Fragments should contain more than one child. ╭─[jsx_no_useless_fragment.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/jsx_props_no_spread_multi.snap b/crates/oxc_linter/src/snapshots/jsx_props_no_spread_multi.snap index 8d3c78bec993a6..020a53299a7250 100644 --- a/crates/oxc_linter/src/snapshots/jsx_props_no_spread_multi.snap +++ b/crates/oxc_linter/src/snapshots/jsx_props_no_spread_multi.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-react(jsx-props-no-spread-multi): Prop 'props' is spread multiple times. ╭─[jsx_props_no_spread_multi.tsx:3:16] diff --git a/crates/oxc_linter/src/snapshots/label_has_associated_control.snap b/crates/oxc_linter/src/snapshots/label_has_associated_control.snap index cb40285f0a6820..d1d6c78b40ff82 100644 --- a/crates/oxc_linter/src/snapshots/label_has_associated_control.snap +++ b/crates/oxc_linter/src/snapshots/label_has_associated_control.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(label-has-associated-control): A form label must be associated with a control. ╭─[label_has_associated_control.tsx:1:1] diff --git a/crates/oxc_linter/src/snapshots/lang.snap b/crates/oxc_linter/src/snapshots/lang.snap index 9bc271ccb1310d..d55ecb18bf2e36 100644 --- a/crates/oxc_linter/src/snapshots/lang.snap +++ b/crates/oxc_linter/src/snapshots/lang.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(lang): Lang attribute must have a valid value. ╭─[lang.tsx:1:7] diff --git a/crates/oxc_linter/src/snapshots/max_classes_per_file.snap b/crates/oxc_linter/src/snapshots/max_classes_per_file.snap index 64347a20cfdf95..4cbd4d776bca7e 100644 --- a/crates/oxc_linter/src/snapshots/max_classes_per_file.snap +++ b/crates/oxc_linter/src/snapshots/max_classes_per_file.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(max-classes-per-file): File has too many classes (2). Maximum allowed is 1 ╭─[max_classes_per_file.tsx:2:4] diff --git a/crates/oxc_linter/src/snapshots/max_dependencies.snap b/crates/oxc_linter/src/snapshots/max_dependencies.snap index b545e447e5cfe1..096a7d4edaee25 100644 --- a/crates/oxc_linter/src/snapshots/max_dependencies.snap +++ b/crates/oxc_linter/src/snapshots/max_dependencies.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-import(max-dependencies): File has too many dependencies (3). Maximum allowed is 1. ╭─[index.ts:3:31] diff --git a/crates/oxc_linter/src/snapshots/max_expects.snap b/crates/oxc_linter/src/snapshots/max_expects.snap index 1ff98d0a38c551..5f94658280d39f 100644 --- a/crates/oxc_linter/src/snapshots/max_expects.snap +++ b/crates/oxc_linter/src/snapshots/max_expects.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jest(max-expects): Enforces a maximum number assertion calls in a test body. ╭─[max_expects.tsx:8:21] diff --git a/crates/oxc_linter/src/snapshots/max_lines.snap b/crates/oxc_linter/src/snapshots/max_lines.snap index 4c5d3d57a59f25..0464fdeb4c4db8 100644 --- a/crates/oxc_linter/src/snapshots/max_lines.snap +++ b/crates/oxc_linter/src/snapshots/max_lines.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(max-lines): File has too many lines (3). ╭─[max_lines.tsx:3:8] diff --git a/crates/oxc_linter/src/snapshots/max_nested_describe.snap b/crates/oxc_linter/src/snapshots/max_nested_describe.snap index a5c9581c2f29d2..47444b8b9d09b6 100644 --- a/crates/oxc_linter/src/snapshots/max_nested_describe.snap +++ b/crates/oxc_linter/src/snapshots/max_nested_describe.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jest(max-nested-describe): Enforces a maximum depth to nested describe calls. ╭─[max_nested_describe.tsx:7:37] diff --git a/crates/oxc_linter/src/snapshots/max_params.snap b/crates/oxc_linter/src/snapshots/max_params.snap index b228f543ea5b4d..d8290c6074e8f7 100644 --- a/crates/oxc_linter/src/snapshots/max_params.snap +++ b/crates/oxc_linter/src/snapshots/max_params.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint(max-params): Function 'test' has too many parameters (3). Maximum allowed is 2. ╭─[max_params.tsx:1:14] diff --git a/crates/oxc_linter/src/snapshots/media_has_caption.snap b/crates/oxc_linter/src/snapshots/media_has_caption.snap index a5016a69be74ed..39abc45d6fd8cf 100644 --- a/crates/oxc_linter/src/snapshots/media_has_caption.snap +++ b/crates/oxc_linter/src/snapshots/media_has_caption.snap @@ -1,5 +1,6 @@ --- source: crates/oxc_linter/src/tester.rs +snapshot_kind: text --- ⚠ eslint-plugin-jsx-a11y(media-has-caption): Missing element with captions inside