mirror of
https://github.com/danbulant/oxc
synced 2026-05-19 04:08:41 +00:00
fix(transformer/arrow-functions): store super_methods on a Stack to fix nested async methods (#8331)
In the following case, async methods can be nested in another async method. The implementation is changing to store `super_methods` on a stack, and then we can store super method information in the correct `super_methods` map.
```js
const outer = {
value: 0,
async method() {
() => super.value;
const inner = {
value: 0,
async method() {
() => super.value;
}
};
() => super.value;
}
};
```
This commit is contained in:
parent
e0a09ab023
commit
e4d66e4636
3 changed files with 26 additions and 29 deletions
|
|
@ -93,7 +93,7 @@ use rustc_hash::{FxBuildHasher, FxHashSet};
|
|||
|
||||
use oxc_allocator::{Box as ArenaBox, Vec as ArenaVec};
|
||||
use oxc_ast::{ast::*, visit::walk_mut::walk_expression, VisitMut, NONE};
|
||||
use oxc_data_structures::stack::{NonEmptyStack, SparseStack};
|
||||
use oxc_data_structures::stack::{NonEmptyStack, SparseStack, Stack};
|
||||
use oxc_semantic::{ReferenceFlags, SymbolId};
|
||||
use oxc_span::{CompactStr, GetSpan, SPAN};
|
||||
use oxc_syntax::{
|
||||
|
|
@ -144,7 +144,7 @@ pub struct ArrowFunctionConverter<'a> {
|
|||
renamed_arguments_symbol_ids: FxHashSet<SymbolId>,
|
||||
// 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<FxIndexMap<SuperMethodKey<'a>, SuperMethodInfo<'a>>>,
|
||||
super_methods_stack: Stack<FxIndexMap<SuperMethodKey<'a>, SuperMethodInfo<'a>>>,
|
||||
}
|
||||
|
||||
impl ArrowFunctionConverter<'_> {
|
||||
|
|
@ -164,7 +164,7 @@ impl ArrowFunctionConverter<'_> {
|
|||
constructor_super_stack: NonEmptyStack::new(false),
|
||||
arguments_needs_transform_stack: NonEmptyStack::new(false),
|
||||
renamed_arguments_symbol_ids: FxHashSet::default(),
|
||||
super_methods: None,
|
||||
super_methods_stack: Stack::new(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -210,7 +210,7 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> {
|
|||
self.constructor_super_stack.push(false);
|
||||
if self.is_async_only() && func.r#async && Self::is_class_method_like_ancestor(ctx.parent())
|
||||
{
|
||||
self.super_methods = Some(FxIndexMap::default());
|
||||
self.super_methods_stack.push(FxIndexMap::default());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -617,7 +617,7 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
/// whose body includes the original `super` expression. The arrow function's name
|
||||
/// is generated based on the property name, such as `_superprop_getProperty`.
|
||||
///
|
||||
/// The `super` expressions are temporarily stored in [`Self::super_methods`]
|
||||
/// The `super` expressions are temporarily stored in [`Self::super_methods_stack`]
|
||||
/// and eventually inserted by [`Self::insert_variable_statement_at_the_top_of_statements`].`
|
||||
///
|
||||
/// ## Example
|
||||
|
|
@ -640,7 +640,7 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
assign_value: Option<&mut Expression<'a>>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Option<Expression<'a>> {
|
||||
let super_methods = self.super_methods.as_mut()?;
|
||||
let super_methods = self.super_methods_stack.last_mut()?;
|
||||
|
||||
let mut argument = None;
|
||||
let mut property = "";
|
||||
|
|
@ -718,7 +718,7 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
call: &mut CallExpression<'a>,
|
||||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Option<Expression<'a>> {
|
||||
if self.super_methods.is_none() || !call.callee.is_member_expression() {
|
||||
if self.super_methods_stack.last().is_none() || !call.callee.is_member_expression() {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
|
@ -757,7 +757,7 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
ctx: &mut TraverseCtx<'a>,
|
||||
) -> Option<Expression<'a>> {
|
||||
// Check if the left of the assignment is a `super` member expression.
|
||||
if self.super_methods.is_none()
|
||||
if self.super_methods_stack.last().is_none()
|
||||
|| !assignment.left.as_member_expression().is_some_and(|m| m.object().is_super())
|
||||
{
|
||||
return None;
|
||||
|
|
@ -1050,10 +1050,11 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
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 super_method_count = self.super_methods.as_ref().map_or(0, FxIndexMap::len);
|
||||
let declarations_count = usize::from(arguments.is_some())
|
||||
+ if is_class_method_like { super_method_count } else { 0 }
|
||||
+ usize::from(this_var.is_some());
|
||||
let super_methods =
|
||||
if is_class_method_like { self.super_methods_stack.pop() } else { None };
|
||||
let super_method_count = super_methods.as_ref().map_or(0, FxIndexMap::len);
|
||||
let declarations_count =
|
||||
usize::from(arguments.is_some()) + super_method_count + usize::from(this_var.is_some());
|
||||
|
||||
// Exit if no declarations to be inserted
|
||||
if declarations_count == 0 {
|
||||
|
|
@ -1070,8 +1071,8 @@ impl<'a> ArrowFunctionConverter<'a> {
|
|||
// `_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(|(key, super_method)| {
|
||||
if let Some(super_methods) = super_methods {
|
||||
declarations.extend(super_methods.into_iter().map(|(key, super_method)| {
|
||||
Self::generate_super_method(
|
||||
target_scope_id,
|
||||
super_method,
|
||||
|
|
|
|||
|
|
@ -42,19 +42,19 @@ after transform: ScopeId(0): ["BrowserWorkingCopyBackupTracker", "CancellationTo
|
|||
rebuilt : ScopeId(0): ["BrowserWorkingCopyBackupTracker", "DisposableStore", "EditorService", "IEditorGroupsService", "IEditorService", "IFilesConfigurationService", "ILifecycleService", "ILogService", "IWorkingCopyBackupService", "IWorkingCopyEditorService", "IWorkingCopyService", "InMemoryTestWorkingCopyBackupService", "LifecyclePhase", "Schemas", "TestServiceAccessor", "TestWorkingCopy", "URI", "UntitledTextEditorInput", "VSBuffer", "_asyncToGenerator", "_defineProperty", "assert", "bufferToReadable", "createEditorPart", "ensureNoDisposablesAreLeakedInTestSuite", "isWindows", "registerTestResourceEditor", "timeout", "toResource", "toTypedWorkingCopyId", "toUntypedWorkingCopyId", "workbenchInstantiationService", "workbenchTeardown"]
|
||||
Symbol reference IDs mismatch for "URI":
|
||||
after transform: SymbolId(1): [ReferenceId(109), ReferenceId(117), ReferenceId(156), ReferenceId(158), ReferenceId(160), ReferenceId(162)]
|
||||
rebuilt : SymbolId(1): [ReferenceId(161), ReferenceId(163), ReferenceId(165), ReferenceId(167)]
|
||||
rebuilt : SymbolId(1): [ReferenceId(160), ReferenceId(162), ReferenceId(164), ReferenceId(166)]
|
||||
Symbol reference IDs mismatch for "IEditorService":
|
||||
after transform: SymbolId(2): [ReferenceId(23), ReferenceId(24), ReferenceId(67), ReferenceId(184)]
|
||||
rebuilt : SymbolId(2): [ReferenceId(17), ReferenceId(60), ReferenceId(188)]
|
||||
rebuilt : SymbolId(2): [ReferenceId(17), ReferenceId(59), ReferenceId(187)]
|
||||
Symbol reference IDs mismatch for "IEditorGroupsService":
|
||||
after transform: SymbolId(4): [ReferenceId(25), ReferenceId(26), ReferenceId(57), ReferenceId(176)]
|
||||
rebuilt : SymbolId(3): [ReferenceId(18), ReferenceId(51), ReferenceId(181)]
|
||||
rebuilt : SymbolId(3): [ReferenceId(18), ReferenceId(50), ReferenceId(180)]
|
||||
Symbol reference IDs mismatch for "EditorService":
|
||||
after transform: SymbolId(5): [ReferenceId(61), ReferenceId(64), ReferenceId(178), ReferenceId(181)]
|
||||
rebuilt : SymbolId(4): [ReferenceId(57), ReferenceId(185)]
|
||||
rebuilt : SymbolId(4): [ReferenceId(56), ReferenceId(184)]
|
||||
Symbol reference IDs mismatch for "IWorkingCopyBackupService":
|
||||
after transform: SymbolId(7): [ReferenceId(11), ReferenceId(12), ReferenceId(51), ReferenceId(170)]
|
||||
rebuilt : SymbolId(5): [ReferenceId(11), ReferenceId(45), ReferenceId(175)]
|
||||
rebuilt : SymbolId(5): [ReferenceId(11), ReferenceId(44), ReferenceId(174)]
|
||||
Symbol reference IDs mismatch for "IFilesConfigurationService":
|
||||
after transform: SymbolId(10): [ReferenceId(13), ReferenceId(14)]
|
||||
rebuilt : SymbolId(8): [ReferenceId(12)]
|
||||
|
|
@ -72,19 +72,19 @@ after transform: SymbolId(17): [ReferenceId(38), ReferenceId(87)]
|
|||
rebuilt : SymbolId(13): [ReferenceId(31)]
|
||||
Symbol reference IDs mismatch for "InMemoryTestWorkingCopyBackupService":
|
||||
after transform: SymbolId(19): [ReferenceId(43), ReferenceId(46), ReferenceId(165)]
|
||||
rebuilt : SymbolId(15): [ReferenceId(40), ReferenceId(170)]
|
||||
rebuilt : SymbolId(15): [ReferenceId(39), ReferenceId(169)]
|
||||
Symbol reference IDs mismatch for "TestServiceAccessor":
|
||||
after transform: SymbolId(21): [ReferenceId(1), ReferenceId(40), ReferenceId(71), ReferenceId(155), ReferenceId(188)]
|
||||
rebuilt : SymbolId(17): [ReferenceId(64), ReferenceId(192)]
|
||||
rebuilt : SymbolId(17): [ReferenceId(63), ReferenceId(191)]
|
||||
Symbol reference IDs mismatch for "IWorkingCopyEditorService":
|
||||
after transform: SymbolId(32): [ReferenceId(21), ReferenceId(22)]
|
||||
rebuilt : SymbolId(26): [ReferenceId(16)]
|
||||
Symbol reference IDs mismatch for "TestWorkingCopyBackupTracker":
|
||||
after transform: SymbolId(39): [ReferenceId(42), ReferenceId(74), ReferenceId(154), ReferenceId(215)]
|
||||
rebuilt : SymbolId(35): [ReferenceId(67), ReferenceId(219)]
|
||||
rebuilt : SymbolId(35): [ReferenceId(66), ReferenceId(218)]
|
||||
Unresolved reference IDs mismatch for "Promise":
|
||||
after transform: [ReferenceId(36), ReferenceId(39), ReferenceId(82), ReferenceId(114), ReferenceId(153), ReferenceId(282)]
|
||||
rebuilt : [ReferenceId(292)]
|
||||
rebuilt : [ReferenceId(291)]
|
||||
|
||||
tasks/coverage/misc/pass/oxc-4449.ts
|
||||
semantic error: Bindings mismatch:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
commit: 54a8389f
|
||||
|
||||
Passed: 122/141
|
||||
Passed: 123/141
|
||||
|
||||
# All Passed:
|
||||
* babel-plugin-transform-class-static-block
|
||||
|
|
@ -9,6 +9,7 @@ Passed: 122/141
|
|||
* babel-plugin-transform-optional-catch-binding
|
||||
* babel-plugin-transform-async-generator-functions
|
||||
* babel-plugin-transform-object-rest-spread
|
||||
* babel-plugin-transform-async-to-generator
|
||||
* babel-plugin-transform-exponentiation-operator
|
||||
* babel-plugin-transform-arrow-functions
|
||||
* babel-preset-typescript
|
||||
|
|
@ -45,11 +46,6 @@ after transform: SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), R
|
|||
rebuilt : SymbolId(0): [ReferenceId(0), ReferenceId(2), ReferenceId(6), ReferenceId(10)]
|
||||
|
||||
|
||||
# babel-plugin-transform-async-to-generator (17/18)
|
||||
* super/nested/input.js
|
||||
x Output mismatch
|
||||
|
||||
|
||||
# babel-plugin-transform-typescript (2/10)
|
||||
* class-property-definition/input.ts
|
||||
Unresolved references mismatch:
|
||||
|
|
|
|||
Loading…
Reference in a new issue