mirror of
https://github.com/danbulant/oxc
synced 2026-05-25 04:42:10 +00:00
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
This commit is contained in:
parent
d445e0f612
commit
7d75130865
13 changed files with 313 additions and 18 deletions
|
|
@ -81,7 +81,7 @@ impl Reference {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[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);
|
self.symbol_id = Some(symbol_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
/// Reserve memory for an `additional` number of scopes.
|
||||||
pub fn reserve(&mut self, additional: usize) {
|
pub fn reserve(&mut self, additional: usize) {
|
||||||
self.parent_ids.reserve(additional);
|
self.parent_ids.reserve(additional);
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,12 @@ impl SymbolTable {
|
||||||
&self.names[symbol_id]
|
&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]
|
#[inline]
|
||||||
pub fn set_name(&mut self, symbol_id: SymbolId, name: CompactStr) {
|
pub fn set_name(&mut self, symbol_id: SymbolId, name: CompactStr) {
|
||||||
self.names[symbol_id] = name;
|
self.names[symbol_id] = name;
|
||||||
|
|
|
||||||
|
|
@ -87,16 +87,18 @@
|
||||||
//! 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 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::*, AstBuilder, NONE};
|
use oxc_ast::{ast::*, AstBuilder, NONE};
|
||||||
use oxc_data_structures::stack::SparseStack;
|
use oxc_data_structures::stack::SparseStack;
|
||||||
use oxc_span::SPAN;
|
use oxc_semantic::{ReferenceFlags, SymbolId};
|
||||||
|
use oxc_span::{CompactStr, SPAN};
|
||||||
use oxc_syntax::{
|
use oxc_syntax::{
|
||||||
scope::{ScopeFlags, ScopeId},
|
scope::{ScopeFlags, ScopeId},
|
||||||
symbol::SymbolFlags,
|
symbol::SymbolFlags,
|
||||||
};
|
};
|
||||||
use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx};
|
use oxc_traverse::{Ancestor, BoundIdentifier, Traverse, TraverseCtx};
|
||||||
use rustc_hash::FxHashMap;
|
|
||||||
|
|
||||||
use crate::EnvOptions;
|
use crate::EnvOptions;
|
||||||
|
|
||||||
|
|
@ -125,6 +127,8 @@ struct SuperMethodInfo<'a> {
|
||||||
pub struct ArrowFunctionConverter<'a> {
|
pub struct ArrowFunctionConverter<'a> {
|
||||||
mode: ArrowFunctionConverterMode,
|
mode: ArrowFunctionConverterMode,
|
||||||
this_var_stack: SparseStack<BoundIdentifier<'a>>,
|
this_var_stack: SparseStack<BoundIdentifier<'a>>,
|
||||||
|
arguments_var_stack: SparseStack<BoundIdentifier<'a>>,
|
||||||
|
renamed_arguments_symbol_ids: FxHashSet<SymbolId>,
|
||||||
super_methods: Option<FxHashMap<Atom<'a>, SuperMethodInfo<'a>>>,
|
super_methods: Option<FxHashMap<Atom<'a>, SuperMethodInfo<'a>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,8 +141,14 @@ impl<'a> ArrowFunctionConverter<'a> {
|
||||||
} else {
|
} else {
|
||||||
ArrowFunctionConverterMode::Disabled
|
ArrowFunctionConverterMode::Disabled
|
||||||
};
|
};
|
||||||
// `SparseStack` is created with 1 empty entry, for `Program`
|
// `SparseStack`s are created with 1 empty entry, for `Program`
|
||||||
Self { mode, this_var_stack: SparseStack::new(), super_methods: None }
|
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 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(
|
self.insert_variable_statement_at_the_top_of_statements(
|
||||||
program.scope_id(),
|
program.scope_id(),
|
||||||
&mut program.body,
|
&mut program.body,
|
||||||
this_var,
|
this_var,
|
||||||
|
arguments_var,
|
||||||
ctx,
|
ctx,
|
||||||
);
|
);
|
||||||
|
|
||||||
debug_assert!(self.this_var_stack.len() == 1);
|
debug_assert!(self.this_var_stack.len() == 1);
|
||||||
debug_assert!(self.this_var_stack.last().is_none());
|
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>) {
|
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.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())
|
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(FxHashMap::default());
|
||||||
|
|
@ -196,10 +212,12 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
let this_var = self.this_var_stack.pop();
|
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(
|
self.insert_variable_statement_at_the_top_of_statements(
|
||||||
scope_id,
|
scope_id,
|
||||||
&mut body.statements,
|
&mut body.statements,
|
||||||
this_var,
|
this_var,
|
||||||
|
arguments_var,
|
||||||
ctx,
|
ctx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -222,6 +240,8 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> {
|
||||||
block.scope_id(),
|
block.scope_id(),
|
||||||
&mut block.body,
|
&mut block.body,
|
||||||
this_var,
|
this_var,
|
||||||
|
// `arguments` is not allowed to be used in static blocks
|
||||||
|
None,
|
||||||
ctx,
|
ctx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -301,6 +321,22 @@ impl<'a> Traverse<'a> for ArrowFunctionConverter<'a> {
|
||||||
*expr = Self::transform_arrow_function_expression(arrow_function_expr, ctx);
|
*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> {
|
impl<'a> ArrowFunctionConverter<'a> {
|
||||||
|
|
@ -787,28 +823,196 @@ impl<'a> ArrowFunctionConverter<'a> {
|
||||||
ast.atom(name.into_bump_str())
|
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<BoundIdentifier<'a>>,
|
||||||
|
ctx: &mut TraverseCtx<'a>,
|
||||||
|
) -> Option<VariableDeclarator<'a>> {
|
||||||
|
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.
|
/// Insert variable statement at the top of the statements.
|
||||||
fn insert_variable_statement_at_the_top_of_statements(
|
fn insert_variable_statement_at_the_top_of_statements(
|
||||||
&mut self,
|
&mut self,
|
||||||
target_scope_id: ScopeId,
|
target_scope_id: ScopeId,
|
||||||
statements: &mut ArenaVec<'a, Statement<'a>>,
|
statements: &mut ArenaVec<'a, Statement<'a>>,
|
||||||
this_var: Option<BoundIdentifier<'a>>,
|
this_var: Option<BoundIdentifier<'a>>,
|
||||||
|
arguments_var: Option<BoundIdentifier<'a>>,
|
||||||
ctx: &mut TraverseCtx<'a>,
|
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;`
|
// `_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() {
|
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)| {
|
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)
|
||||||
}));
|
}));
|
||||||
declarations
|
|
||||||
} else {
|
|
||||||
ctx.ast.vec_with_capacity(1)
|
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
ctx.ast.vec_with_capacity(1)
|
|
||||||
};
|
|
||||||
|
|
||||||
// `_this = this;`
|
// `_this = this;`
|
||||||
if let Some(this_var) = this_var {
|
if let Some(this_var) = this_var {
|
||||||
|
|
@ -823,10 +1027,7 @@ impl<'a> ArrowFunctionConverter<'a> {
|
||||||
declarations.push(variable_declarator);
|
declarations.push(variable_declarator);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there are no declarations, we don't need to insert a variable declaration.
|
debug_assert_eq!(declarations_count, declarations.len());
|
||||||
if declarations.is_empty() {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let stmt = ctx.ast.alloc_variable_declaration(
|
let stmt = ctx.ast.alloc_variable_declaration(
|
||||||
SPAN,
|
SPAN,
|
||||||
|
|
|
||||||
|
|
@ -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>) {
|
fn exit_expression(&mut self, expr: &mut Expression<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||||
self.arrow_function_converter.exit_expression(expr, ctx);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,22 @@ impl<'a, 'ctx> Traverse<'a> for TransformerImpl<'a, 'ctx> {
|
||||||
self.x2_es2020.enter_big_int_literal(node, 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>) {
|
fn enter_binding_pattern(&mut self, pat: &mut BindingPattern<'a>, ctx: &mut TraverseCtx<'a>) {
|
||||||
if let Some(typescript) = self.x0_typescript.as_mut() {
|
if let Some(typescript) = self.x0_typescript.as_mut() {
|
||||||
typescript.enter_binding_pattern(pat, ctx);
|
typescript.enter_binding_pattern(pat, ctx);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
commit: d20b314c
|
commit: d20b314c
|
||||||
|
|
||||||
Passed: 82/92
|
Passed: 85/95
|
||||||
|
|
||||||
# All Passed:
|
# All Passed:
|
||||||
* babel-plugin-transform-class-static-block
|
* babel-plugin-transform-class-static-block
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
const ArgumentsAssignment = async () => {
|
||||||
|
let arguments = arguments;
|
||||||
|
console.log(arguments);
|
||||||
|
};
|
||||||
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}();
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
class Cls {
|
||||||
|
async method() {
|
||||||
|
() => {
|
||||||
|
console.log(arguments);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
class Cls {
|
||||||
|
method() {
|
||||||
|
var _arguments = arguments;
|
||||||
|
return babelHelpers.asyncToGenerator(function* () {
|
||||||
|
() => {
|
||||||
|
console.log(_arguments);
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
const ArrowFunction = async () => {
|
||||||
|
{
|
||||||
|
var arguments = arguments;
|
||||||
|
console.log(arguments);
|
||||||
|
}
|
||||||
|
console.log(arguments);
|
||||||
|
};
|
||||||
|
|
@ -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);
|
||||||
|
};
|
||||||
|
}();
|
||||||
Loading…
Reference in a new issue