From 87fd942c99da3c9b8954c201090bbf84a9deec32 Mon Sep 17 00:00:00 2001 From: Dunqing Date: Mon, 4 Nov 2024 19:53:37 +0800 Subject: [PATCH] feat(transformer): enable ArrowFunctionConverter in async-to-generator and async-generator-functions plugins --- .../src/common/arrow_function_converter.rs | 62 +++- crates/oxc_transformer/src/common/mod.rs | 17 +- .../src/es2017/async_to_generator.rs | 9 +- .../es2018/async_generator_functions/mod.rs | 6 +- .../snapshots/babel.snap.md | 30 +- .../snapshots/babel_exec.snap.md | 266 +----------------- 6 files changed, 92 insertions(+), 298 deletions(-) diff --git a/crates/oxc_transformer/src/common/arrow_function_converter.rs b/crates/oxc_transformer/src/common/arrow_function_converter.rs index 4c99899cbbc6d0..993c44d5a9d950 100644 --- a/crates/oxc_transformer/src/common/arrow_function_converter.rs +++ b/crates/oxc_transformer/src/common/arrow_function_converter.rs @@ -97,6 +97,8 @@ use oxc_syntax::{ }; use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx}; +use crate::TransformOptions; + /// Mode for arrow function conversion #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum ArrowFunctionConverterMode { @@ -107,23 +109,27 @@ pub enum ArrowFunctionConverterMode { Enabled, /// Only convert async arrow functions - #[expect(unused)] AsyncOnly, } -pub struct ArrowFunctionConverterOptions { - pub mode: ArrowFunctionConverterMode, -} - pub struct ArrowFunctionConverter<'a> { mode: ArrowFunctionConverterMode, this_var_stack: SparseStack>, } impl<'a> ArrowFunctionConverter<'a> { - pub fn new(options: &ArrowFunctionConverterOptions) -> Self { + pub fn new(options: &TransformOptions) -> Self { + let mode = if options.env.es2015.arrow_function.is_some() { + ArrowFunctionConverterMode::Enabled + } else if options.env.es2017.async_to_generator + || options.env.es2018.async_generator_functions + { + ArrowFunctionConverterMode::AsyncOnly + } else { + ArrowFunctionConverterMode::Disabled + }; // `SparseStack` is created with 1 empty entry, for `Program` - Self { mode: options.mode, this_var_stack: SparseStack::new() } + Self { mode, this_var_stack: SparseStack::new() } } } @@ -254,7 +260,11 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> { return; } - if let Expression::ArrowFunctionExpression(_) = expr { + if let Expression::ArrowFunctionExpression(arrow_function_expr) = expr { + if self.is_async_only() && !arrow_function_expr.r#async { + return; + } + let Expression::ArrowFunctionExpression(arrow_function_expr) = ctx.ast.move_expression(expr) else { @@ -272,13 +282,18 @@ impl<'a> ArrowFunctionConverter<'a> { self.mode == ArrowFunctionConverterMode::Disabled } + /// Check if arrow function conversion has enabled for transform async arrow functions + fn is_async_only(&self) -> bool { + self.mode == ArrowFunctionConverterMode::AsyncOnly + } + fn get_this_identifier( &mut self, span: Span, ctx: &mut TraverseCtx<'a>, ) -> Option>> { // Find arrow function we are currently in (if we are) - let arrow_scope_id = Self::get_arrow_function_scope(ctx)?; + let arrow_scope_id = self.get_arrow_function_scope(ctx)?; // TODO(improve-on-babel): We create a new UID for every scope. This is pointless, as only one // `this` can be in scope at a time. We could create a single `_this` UID and reuse it in each @@ -304,7 +319,7 @@ impl<'a> ArrowFunctionConverter<'a> { /// Find arrow function we are currently in, if it's between current node, and where `this` is bound. /// Return its `ScopeId`. - fn get_arrow_function_scope(ctx: &mut TraverseCtx<'a>) -> Option { + fn get_arrow_function_scope(&self, ctx: &mut TraverseCtx<'a>) -> Option { // `this` inside a class resolves to `this` *outside* the class in: // * `extends` clause // * Computed method key @@ -346,13 +361,13 @@ impl<'a> ArrowFunctionConverter<'a> { // ``` // // So in this loop, we only exit when we encounter one of the above. - for ancestor in ctx.ancestors() { + let mut ancestors = ctx.ancestors(); + while let Some(ancestor) = ancestors.next() { match ancestor { // Top level Ancestor::ProgramBody(_) // Function (includes class method body) | Ancestor::FunctionParams(_) - | Ancestor::FunctionBody(_) // Class property body | Ancestor::PropertyDefinitionValue(_) // Class accessor property body @@ -361,10 +376,29 @@ impl<'a> ArrowFunctionConverter<'a> { | Ancestor::StaticBlockBody(_) => return None, // Arrow function Ancestor::ArrowFunctionExpressionParams(func) => { - return Some(func.scope_id().get().unwrap()) + return if self.is_async_only() && !*func.r#async() { + None + } else { + Some(func.scope_id().get().unwrap()) + } } Ancestor::ArrowFunctionExpressionBody(func) => { - return Some(func.scope_id().get().unwrap()) + return if self.is_async_only() && !*func.r#async() { + None + } else { + Some(func.scope_id().get().unwrap()) + } + } + Ancestor::FunctionBody(func) => { + return if self.is_async_only() && *func.r#async() + && matches!( + ancestors.next().unwrap(), + Ancestor::MethodDefinitionValue(_) | Ancestor::ObjectPropertyValue(_) + ) { + Some(func.scope_id().get().unwrap()) + } else { + None + } } _ => {} } diff --git a/crates/oxc_transformer/src/common/mod.rs b/crates/oxc_transformer/src/common/mod.rs index cb8d995540f9da..8c6ba957e0b583 100644 --- a/crates/oxc_transformer/src/common/mod.rs +++ b/crates/oxc_transformer/src/common/mod.rs @@ -1,8 +1,6 @@ //! Utility transforms which are in common between other transforms. -use arrow_function_converter::{ - ArrowFunctionConverter, ArrowFunctionConverterMode, ArrowFunctionConverterOptions, -}; +use arrow_function_converter::ArrowFunctionConverter; use oxc_allocator::Vec as ArenaVec; use oxc_ast::ast::*; use oxc_traverse::{Traverse, TraverseCtx}; @@ -31,23 +29,12 @@ pub struct Common<'a, 'ctx> { impl<'a, 'ctx> Common<'a, 'ctx> { pub fn new(options: &TransformOptions, ctx: &'ctx TransformCtx<'a>) -> Self { - let arrow_function_converter_options = { - let mode = if options.env.es2015.arrow_function.is_some() { - ArrowFunctionConverterMode::Enabled - } else { - ArrowFunctionConverterMode::Disabled - }; - ArrowFunctionConverterOptions { mode } - }; - Self { module_imports: ModuleImports::new(ctx), var_declarations: VarDeclarations::new(ctx), statement_injector: StatementInjector::new(ctx), top_level_statements: TopLevelStatements::new(ctx), - arrow_function_converter: ArrowFunctionConverter::new( - &arrow_function_converter_options, - ), + arrow_function_converter: ArrowFunctionConverter::new(options), } } } diff --git a/crates/oxc_transformer/src/es2017/async_to_generator.rs b/crates/oxc_transformer/src/es2017/async_to_generator.rs index 7b52e56f3c9cce..81d6159a6ab61c 100644 --- a/crates/oxc_transformer/src/es2017/async_to_generator.rs +++ b/crates/oxc_transformer/src/es2017/async_to_generator.rs @@ -131,7 +131,14 @@ impl<'a, 'ctx> Traverse<'a> for AsyncToGenerator<'a, 'ctx> { } fn exit_function(&mut self, func: &mut Function<'a>, ctx: &mut TraverseCtx<'a>) { - if func.r#async && matches!(ctx.parent(), Ancestor::MethodDefinitionValue(_)) { + if func.r#async + && !func.is_typescript_syntax() + && matches!( + ctx.parent(), + // `class A { async foo() {} }` | `({ async foo() {} })` + Ancestor::MethodDefinitionValue(_) | Ancestor::PropertyDefinitionValue(_) + ) + { self.executor.transform_function_for_method_definition(func, 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 22fdf5de874a72..d048d9206da68f 100644 --- a/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs +++ b/crates/oxc_transformer/src/es2018/async_generator_functions/mod.rs @@ -172,7 +172,11 @@ impl<'a, 'ctx> Traverse<'a> for AsyncGeneratorFunctions<'a, 'ctx> { if func.r#async && func.generator && !func.is_typescript_syntax() - && matches!(ctx.parent(), Ancestor::MethodDefinitionValue(_)) + && matches!( + ctx.parent(), + // `class A { async foo() {} }` | `({ async foo() {} })` + Ancestor::MethodDefinitionValue(_) | Ancestor::ObjectPropertyValue(_) + ) { self.executor.transform_function_for_method_definition(func, ctx); } diff --git a/tasks/transform_conformance/snapshots/babel.snap.md b/tasks/transform_conformance/snapshots/babel.snap.md index 22a15bcaf0116d..577ab810d9bd98 100644 --- a/tasks/transform_conformance/snapshots/babel.snap.md +++ b/tasks/transform_conformance/snapshots/babel.snap.md @@ -1452,13 +1452,37 @@ x Output mismatch # babel-plugin-transform-async-generator-functions (15/19) * async-generators/class-method/input.js -x Output mismatch +Bindings mismatch: +after transform: ScopeId(0): ["C", "_this"] +rebuilt : ScopeId(0): ["C"] +Bindings mismatch: +after transform: ScopeId(3): [] +rebuilt : ScopeId(2): ["_this"] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(0) +rebuilt : SymbolId(1): ScopeId(2) * async-generators/object-method/input.js -x Output mismatch +Bindings mismatch: +after transform: ScopeId(0): ["_this"] +rebuilt : ScopeId(0): [] +Bindings mismatch: +after transform: ScopeId(2): [] +rebuilt : ScopeId(1): ["_this"] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(0): ScopeId(0) +rebuilt : SymbolId(0): ScopeId(1) * async-generators/static-method/input.js -x Output mismatch +Bindings mismatch: +after transform: ScopeId(0): ["C", "_this"] +rebuilt : ScopeId(0): ["C"] +Bindings mismatch: +after transform: ScopeId(3): [] +rebuilt : ScopeId(2): ["_this"] +Symbol scope ID mismatch for "_this": +after transform: SymbolId(1): ScopeId(0) +rebuilt : SymbolId(1): ScopeId(2) * nested/arrows-in-declaration/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 5f39b203e7c90e..d271e02df08a07 100644 --- a/tasks/transform_conformance/snapshots/babel_exec.snap.md +++ b/tasks/transform_conformance/snapshots/babel_exec.snap.md @@ -1,266 +1,4 @@ commit: d20b314c -node: v22.11.0 -⎯⎯⎯⎯⎯⎯ Failed Suites 1 ⎯⎯⎯⎯⎯⎯⎯ - - 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.8.4/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:52319:11 - ❯ loadAndTransform ../../node_modules/.pnpm/vite@5.4.8_@types+node@22.8.4/node_modules/vite/dist/node/chunks/dep-CDnG8rE7.js:51917:72 - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[1/14]⎯ - -⎯⎯⎯⎯⎯⎯ Failed Tests 13 ⎯⎯⎯⎯⎯⎯⎯ - - 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/14]⎯ - - 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/14]⎯ - - 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:12:14 - 10| } }; - 11| let res = _objectSpread(_objectSpread(_objectSpread({}, withFoo), { m… - 12| expect(res).toEqual({ - | ^ - 13| foo: 0, - 14| middle: 0, - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[4/14]⎯ - - 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(); - | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[5/14]⎯ - - 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(); - | ^ - 14| const obj2 = { "NOWRITE": 456 }; - 15| expect(() => { - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[6/14]⎯ - - 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:10:14 - 8| log.push(2); - 9| } }); - 10| expect(log).toEqual([1]); - | ^ - 11| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[7/14]⎯ - - 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/14]⎯ - - 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/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]⎯ - - 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 - -- Expected: -undefined - -+ Received: -"ReferenceError: x is not defined" - - ❯ fixtures/babel-preset-env-test-fixtures-plugins-integration-issue-15170-exec.test.js:6:9 - 4| expect(() => { - 5| x = async (x) => 0; - 6| }).not.toThrow(); - | ^ - 7| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[12/14]⎯ - - FAIL fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js > exec -TypeError: Assignment to constant variable. - ❯ fixtures/babel-preset-env-test-fixtures-sanity-check-es2015-constants-exec.test.js:5:6 - 3| test("exec", () => { - 4| const one = 123; - 5| one = 432; - | ^ - 6| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[13/14]⎯ - - FAIL fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js > exec -AssertionError: expected false to be true // Object.is equality - -- Expected -+ Received - -- true -+ false - - ❯ fixtures/babel-preset-env-test-fixtures-sanity-regex-dot-all-exec.test.js:10:37 - 8| expect(/hello.world/.test(input)).toBe(false); - 9| expect(/hello.world/u.test(input)).toBe(false); - 10| expect(/hello.world/s.test(input)).toBe(true); - | ^ - 11| expect(/hello.world/su.test(input)).toBe(true); - 12| }) - -⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯[14/14]⎯ - - -⎯⎯⎯⎯ Unhandled Rejection ⎯⎯⎯⎯⎯ -AssertionError: expected [Function Object] to be [Function Bar] // Object.is equality - -- Expected -+ Received - -- [Function Bar] -+ [Function Object] - - ❯ fixtures/babel-preset-env-test-fixtures-plugins-integration-regression-7064-exec.test.js:13:30 - 11| }).call(this); - 12| _asyncToGenerator(function* () { - 13| expect(this.constructor).toBe(Bar); - | ^ - 14| })(); - 15| _asyncToGenerator(function* () { - ❯ asyncGeneratorStep ../../node_modules/.pnpm/@babel+runtime@7.26.0/node_modules/@babel/runtime/helpers/asyncToGenerator.js:3:17 - ❯ _next ../../node_modules/.pnpm/@babel+runtime@7.26.0/node_modules/@babel/runtime/helpers/asyncToGenerator.js:17:9 - ❯ ../../node_modules/.pnpm/@babel+runtime@7.26.0/node_modules/@babel/runtime/helpers/asyncToGenerator.js:22:7 - ❯ ../../node_modules/.pnpm/@babel+runtime@7.26.0/node_modules/@babel/runtime/helpers/asyncToGenerator.js:14:12 - ❯ Bar.test fixtures/babel-preset-env-test-fixtures-plugins-integration-regression-7064-exec.test.js:14:6 - ❯ fixtures/babel-preset-env-test-fixtures-plugins-integration-regression-7064-exec.test.js:20:12 - ❯ ../../node_modules/.pnpm/@vitest+runner@2.1.2/node_modules/@vitest/runner/dist/index.js:146:14 - -This error originated in "fixtures/babel-preset-env-test-fixtures-plugins-integration-regression-7064-exec.test.js" test file. It doesn't mean the error was thrown inside the file itself, but while it was running. -The latest test that might've caused the error is "fixtures/babel-preset-env-test-fixtures-plugins-integration-regression-7064-exec.test.js". It might mean one of the following: -- The error was thrown, while Vitest was running this test. -- If the error occurred after the test had been completed, this was the last documented test before it was thrown. - +node: v20.16.0 +node: bad option: --run