mirror of
https://github.com/swc-project/swc.git
synced 2024-11-23 09:38:16 +03:00
fix(es/transforms/compat): Remove .bind(this)
(#2776)
swc_ecma_transforms_compat: - `async_to_generator`: Create `_this` instead of using `.bind(this)`.
This commit is contained in:
parent
8615a64f2f
commit
5261df52d2
@ -30,16 +30,17 @@ function _asyncToGenerator(fn) {
|
||||
}
|
||||
class A {
|
||||
foo() {
|
||||
return _asyncToGenerator((function*() {
|
||||
var _this = this;
|
||||
return _asyncToGenerator(function*() {
|
||||
try {
|
||||
return yield _asyncToGenerator((function*(x) {
|
||||
return x + this.val;
|
||||
}).bind(this)).bind(this)('a'); // this is undefined
|
||||
return yield _asyncToGenerator(function*(x) {
|
||||
return x + _this.val;
|
||||
})('a'); // this is undefined
|
||||
// return await Promise.all(['a', 'b'].map(async (x) => x + this.val)); // this is undefined
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}).bind(this))();
|
||||
})();
|
||||
}
|
||||
constructor(){
|
||||
this.val = '1';
|
||||
|
@ -63,8 +63,6 @@ impl AsyncToGenerator {
|
||||
T: StmtLike + VisitMutWith<Actual>,
|
||||
Vec<T>: VisitMutWith<Self>,
|
||||
{
|
||||
stmts.visit_mut_children_with(self);
|
||||
|
||||
let mut stmts_updated = Vec::with_capacity(stmts.len());
|
||||
|
||||
for mut stmt in stmts.drain(..) {
|
||||
@ -80,6 +78,7 @@ impl AsyncToGenerator {
|
||||
}
|
||||
|
||||
*stmts = stmts_updated;
|
||||
stmts.visit_mut_children_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
@ -121,17 +120,38 @@ impl VisitMut for Actual {
|
||||
}
|
||||
let params = m.function.params.clone();
|
||||
|
||||
let mut folder = MethodFolder { vars: vec![] };
|
||||
let mut folder = MethodFolder {
|
||||
vars: vec![],
|
||||
scoped_this_ident: None,
|
||||
};
|
||||
m.function.params.clear();
|
||||
|
||||
m.function.visit_mut_children_with(&mut folder);
|
||||
|
||||
let this_decl = if let Some(this_ident) = folder.scoped_this_ident {
|
||||
let decl = VarDecl {
|
||||
span: DUMMY_SP,
|
||||
kind: VarDeclKind::Var,
|
||||
declare: false,
|
||||
decls: vec![VarDeclarator {
|
||||
span: DUMMY_SP,
|
||||
name: Pat::Ident(this_ident.into()),
|
||||
init: Some(Box::new(Expr::This(ThisExpr { span: DUMMY_SP }))),
|
||||
definite: false,
|
||||
}],
|
||||
};
|
||||
|
||||
Some(Stmt::Decl(Decl::Var(decl)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let expr = make_fn_ref(
|
||||
FnExpr {
|
||||
ident: None,
|
||||
function: m.function.take(),
|
||||
},
|
||||
self.in_object_prop || self.in_prototype_assignment,
|
||||
false,
|
||||
);
|
||||
|
||||
let hoisted_super = if folder.vars.is_empty() {
|
||||
@ -154,6 +174,7 @@ impl VisitMut for Actual {
|
||||
span: DUMMY_SP,
|
||||
stmts: hoisted_super
|
||||
.into_iter()
|
||||
.chain(this_decl.into_iter())
|
||||
.chain(iter::once(Stmt::Return(ReturnStmt {
|
||||
span: DUMMY_SP,
|
||||
arg: Some(Box::new(Expr::Call(CallExpr {
|
||||
@ -459,6 +480,49 @@ impl VisitMut for Actual {
|
||||
fn visit_mut_stmts(&mut self, _n: &mut Vec<Stmt>) {}
|
||||
}
|
||||
|
||||
struct ThisReplacer<'a> {
|
||||
to: &'a Ident,
|
||||
}
|
||||
|
||||
impl VisitMut for ThisReplacer<'_> {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_arrow_expr(&mut self, _: &mut ArrowExpr) {}
|
||||
|
||||
fn visit_mut_constructor(&mut self, _: &mut Constructor) {}
|
||||
|
||||
fn visit_mut_expr(&mut self, e: &mut Expr) {
|
||||
e.visit_mut_children_with(self);
|
||||
|
||||
match e {
|
||||
Expr::This(..) => {
|
||||
*e = Expr::Ident(self.to.clone());
|
||||
}
|
||||
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mut_function(&mut self, _: &mut Function) {}
|
||||
|
||||
/// Don't recurse into fn
|
||||
fn visit_mut_getter_prop(&mut self, n: &mut GetterProp) {
|
||||
n.key.visit_mut_with(self);
|
||||
}
|
||||
|
||||
/// Don't recurse into fn
|
||||
fn visit_mut_method_prop(&mut self, n: &mut MethodProp) {
|
||||
n.key.visit_mut_with(self);
|
||||
n.function.visit_mut_with(self);
|
||||
}
|
||||
|
||||
/// Don't recurse into fn
|
||||
fn visit_mut_setter_prop(&mut self, n: &mut SetterProp) {
|
||||
n.key.visit_mut_with(self);
|
||||
n.param.visit_mut_with(self);
|
||||
}
|
||||
}
|
||||
|
||||
/// Hoists super access
|
||||
///
|
||||
/// ## In
|
||||
@ -489,6 +553,7 @@ impl VisitMut for Actual {
|
||||
/// ```
|
||||
struct MethodFolder {
|
||||
vars: Vec<VarDeclarator>,
|
||||
scoped_this_ident: Option<Ident>,
|
||||
}
|
||||
|
||||
impl MethodFolder {
|
||||
@ -564,6 +629,35 @@ impl VisitMut for MethodFolder {
|
||||
noop_visit_mut_type!();
|
||||
|
||||
fn visit_mut_expr(&mut self, expr: &mut Expr) {
|
||||
match expr {
|
||||
Expr::Arrow(ArrowExpr { body, .. }) if contains_this_expr(body) => {
|
||||
let this_id = self
|
||||
.scoped_this_ident
|
||||
.get_or_insert(private_ident!("_this"))
|
||||
.clone();
|
||||
|
||||
body.visit_mut_with(&mut ThisReplacer { to: &this_id });
|
||||
}
|
||||
Expr::Fn(FnExpr {
|
||||
function: Function {
|
||||
body: Some(body), ..
|
||||
},
|
||||
..
|
||||
}) if contains_this_expr(body) => {
|
||||
if self.scoped_this_ident.is_none() {
|
||||
self.scoped_this_ident = Some(private_ident!("_this"));
|
||||
}
|
||||
|
||||
body.visit_mut_with(&mut ThisReplacer {
|
||||
to: &self
|
||||
.scoped_this_ident
|
||||
.clone()
|
||||
.expect("this scope should exist"),
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
|
||||
// TODO(kdy): Cache (Reuse declaration for same property)
|
||||
|
||||
match expr {
|
||||
|
@ -994,34 +994,35 @@ class Class {
|
||||
r#"
|
||||
class Class {
|
||||
method() {
|
||||
return _asyncToGenerator((function*() {
|
||||
this;
|
||||
()=>this
|
||||
;
|
||||
()=>{
|
||||
this;
|
||||
()=>this
|
||||
;
|
||||
function x() {
|
||||
this;
|
||||
()=>{
|
||||
this;
|
||||
};
|
||||
_asyncToGenerator((function*() {
|
||||
this;
|
||||
}).bind(this)).bind(this);
|
||||
}
|
||||
};
|
||||
function x() {
|
||||
this;
|
||||
()=>{
|
||||
this;
|
||||
};
|
||||
_asyncToGenerator((function*() {
|
||||
this;
|
||||
}).bind(this)).bind(this);
|
||||
}
|
||||
}).bind(this))();
|
||||
var _this = this;
|
||||
return _asyncToGenerator((function*() {
|
||||
this;
|
||||
()=>_this
|
||||
;
|
||||
()=>{
|
||||
_this;
|
||||
()=>_this
|
||||
;
|
||||
function x() {
|
||||
this;
|
||||
()=>{
|
||||
_this;
|
||||
};
|
||||
_asyncToGenerator(function*() {
|
||||
_this;
|
||||
});
|
||||
}
|
||||
};
|
||||
function x() {
|
||||
this;
|
||||
()=>{
|
||||
_this;
|
||||
};
|
||||
_asyncToGenerator(function*() {
|
||||
_this;
|
||||
});
|
||||
}
|
||||
}).bind(this))();
|
||||
}
|
||||
}
|
||||
"#
|
||||
@ -2261,15 +2262,16 @@ test!(
|
||||
class A {
|
||||
val = '1';
|
||||
foo() {
|
||||
return _asyncToGenerator((function*() {
|
||||
try {
|
||||
return yield _asyncToGenerator((function*(x) {
|
||||
return x + this.val;
|
||||
}).bind(this)).bind(this)('a');
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
}).bind(this))();
|
||||
var _this = this;
|
||||
return _asyncToGenerator(function*() {
|
||||
try {
|
||||
return yield _asyncToGenerator(function*(x) {
|
||||
return x + _this.val;
|
||||
})('a');
|
||||
} catch (e) {
|
||||
throw e;
|
||||
}
|
||||
})();
|
||||
}
|
||||
}
|
||||
"
|
||||
@ -2315,11 +2317,12 @@ test!(
|
||||
class A {
|
||||
val = '1';
|
||||
foo() {
|
||||
return _asyncToGenerator((function*() {
|
||||
return yield _asyncToGenerator((function*(x) {
|
||||
return x + this.val;
|
||||
}).bind(this)).bind(this)('a');
|
||||
}).bind(this))();
|
||||
var _this = this;
|
||||
return _asyncToGenerator(function*() {
|
||||
return yield _asyncToGenerator(function*(x) {
|
||||
return x + _this.val;
|
||||
})('a');
|
||||
})();
|
||||
}
|
||||
}
|
||||
"
|
||||
|
Loading…
Reference in New Issue
Block a user