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.
This commit is contained in:
overlookmotel 2024-11-17 05:08:57 +00:00 committed by overlookmotel
parent 0a2470399e
commit 5d853869eb
2 changed files with 17 additions and 10 deletions

View file

@ -87,7 +87,10 @@
//! The Implementation based on //! The Implementation based on
//! <https://github.com/babel/babel/blob/d20b314c14533ab86351ecf6ca6b7296b66a57b3/packages/babel-traverse/src/path/conversion.ts#L170-L247> //! <https://github.com/babel/babel/blob/d20b314c14533ab86351ecf6ca6b7296b66a57b3/packages/babel-traverse/src/path/conversion.ts#L170-L247>
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_allocator::{Box as ArenaBox, String as ArenaString, Vec as ArenaVec};
use oxc_ast::{ast::*, NONE}; use oxc_ast::{ast::*, NONE};
@ -102,6 +105,8 @@ use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx};
use crate::EnvOptions; use crate::EnvOptions;
type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
/// Mode for arrow function conversion /// Mode for arrow function conversion
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ArrowFunctionConverterMode { pub enum ArrowFunctionConverterMode {
@ -129,7 +134,9 @@ pub struct ArrowFunctionConverter<'a> {
this_var_stack: SparseStack<BoundIdentifier<'a>>, this_var_stack: SparseStack<BoundIdentifier<'a>>,
arguments_var_stack: SparseStack<BoundIdentifier<'a>>, arguments_var_stack: SparseStack<BoundIdentifier<'a>>,
renamed_arguments_symbol_ids: FxHashSet<SymbolId>, renamed_arguments_symbol_ids: FxHashSet<SymbolId>,
super_methods: Option<FxHashMap<Atom<'a>, 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<FxIndexMap<Atom<'a>, SuperMethodInfo<'a>>>,
} }
impl<'a> ArrowFunctionConverter<'a> { impl<'a> ArrowFunctionConverter<'a> {
@ -187,7 +194,7 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> {
self.arguments_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()) 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 is_class_method_like = Self::is_class_method_like_ancestor(ctx.parent());
let declarations_count = usize::from(arguments.is_some()) let declarations_count = usize::from(arguments.is_some())
+ if is_class_method_like { + 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 { } else {
0 0
} }
@ -1033,7 +1040,7 @@ impl<'a> ArrowFunctionConverter<'a> {
// `_superprop_getSomething = () => super.getSomething;` // `_superprop_getSomething = () => super.getSomething;`
if is_class_method_like { if is_class_method_like {
if let Some(super_methods) = self.super_methods.as_mut() { 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) Self::generate_super_method(target_scope_id, super_method, ctx)
})); }));
} }

View file

@ -1,15 +1,15 @@
const Obj = { const Obj = {
value: 0, value: 0,
method() { method() {
var _superprop_getObject = () => super.object, var _superprop_setValue = (_value) => (super.value = _value),
_superprop_set = (_prop, _value) => super[_prop] = _value, _superprop_set = (_prop, _value2) => (super[_prop] = _value2),
_superprop_setValue = _value2 => super.value = _value2; _superprop_getObject = () => super.object;
return babelHelpers.asyncToGenerator(function* () { return babelHelpers.asyncToGenerator(function* () {
_superprop_setValue(true); _superprop_setValue(true);
() => { () => {
_superprop_set('value', true); _superprop_set("value", true);
_superprop_getObject().value = true; _superprop_getObject().value = true;
}; };
})(); })();
} }
}; };