Skip to content

Commit e764df2

Browse files
authored
fix(es/compat): Hoist arguments in object method while lowering async functions (#10167)
**Related issue:** - Closes #10149
1 parent 724c99f commit e764df2

File tree

10 files changed

+186
-43
lines changed

10 files changed

+186
-43
lines changed

.changeset/foo-bar.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
swc_ecma_compat_es2017: patch
3+
swc_core: patch
4+
---
5+
6+
fix(es/compat): Hoist arguments in object method while lowering async functions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "ecmascript",
5+
"jsx": false
6+
},
7+
"target": "es5"
8+
},
9+
"minify": false,
10+
"isModule": true
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var foo = {
2+
async bar({ name }) {
3+
console.log("arguments.length", arguments.length);
4+
},
5+
};
6+
7+
class Foo {
8+
async bar({ name }) {
9+
console.log("arguments.length", arguments.length);
10+
}
11+
}
12+
13+
async function bar({ name }) {
14+
console.log("arguments.length", arguments.length);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
var _async_to_generator = require("@swc/helpers/_/_async_to_generator");
2+
var _class_call_check = require("@swc/helpers/_/_class_call_check");
3+
var _create_class = require("@swc/helpers/_/_create_class");
4+
var _ts_generator = require("@swc/helpers/_/_ts_generator");
5+
var foo = {
6+
bar: function bar(param) {
7+
var name = param.name;
8+
var _arguments = arguments;
9+
return _async_to_generator._(function() {
10+
return _ts_generator._(this, function(_state) {
11+
console.log("arguments.length", _arguments.length);
12+
return [
13+
2
14+
];
15+
});
16+
})();
17+
}
18+
};
19+
var Foo = /*#__PURE__*/ function() {
20+
"use strict";
21+
function Foo() {
22+
_class_call_check._(this, Foo);
23+
}
24+
_create_class._(Foo, [
25+
{
26+
key: "bar",
27+
value: function bar(param) {
28+
var name = param.name;
29+
var _arguments = arguments;
30+
return _async_to_generator._(function() {
31+
return _ts_generator._(this, function(_state) {
32+
console.log("arguments.length", _arguments.length);
33+
return [
34+
2
35+
];
36+
});
37+
})();
38+
}
39+
}
40+
]);
41+
return Foo;
42+
}();
43+
function bar(_) {
44+
return _bar.apply(this, arguments);
45+
}
46+
function _bar() {
47+
_bar = _async_to_generator._(function(param) {
48+
var name;
49+
var _arguments = arguments;
50+
return _ts_generator._(this, function(_state) {
51+
name = param.name;
52+
console.log("arguments.length", _arguments.length);
53+
return [
54+
2
55+
];
56+
});
57+
});
58+
return _bar.apply(this, arguments);
59+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"jsc": {
3+
"parser": {
4+
"syntax": "ecmascript",
5+
"jsx": false
6+
},
7+
"target": "es2016"
8+
},
9+
"minify": false,
10+
"isModule": true
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
var foo = {
2+
async bar({ name }) {
3+
console.log("arguments.length", arguments.length);
4+
},
5+
};
6+
7+
class Foo {
8+
async bar({ name }) {
9+
console.log("arguments.length", arguments.length);
10+
}
11+
}
12+
13+
async function bar({ name }) {
14+
console.log("arguments.length", arguments.length);
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
var _async_to_generator = require("@swc/helpers/_/_async_to_generator");
2+
var foo = {
3+
bar ({ name }) {
4+
var _arguments = arguments;
5+
return _async_to_generator._(function*() {
6+
console.log("arguments.length", _arguments.length);
7+
})();
8+
}
9+
};
10+
class Foo {
11+
bar({ name }) {
12+
var _arguments = arguments;
13+
return _async_to_generator._(function*() {
14+
console.log("arguments.length", _arguments.length);
15+
})();
16+
}
17+
}
18+
function bar(_) {
19+
return _bar.apply(this, arguments);
20+
}
21+
function _bar() {
22+
_bar = _async_to_generator._(function*({ name }) {
23+
console.log("arguments.length", arguments.length);
24+
});
25+
return _bar.apply(this, arguments);
26+
}

crates/swc/tests/fixture/issues-1xxx/1575/case1/output/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ var _ts_generator = require("@swc/helpers/_/_ts_generator");
33
Vue.component("test", {
44
methods: {
55
onSend: function onSend() {
6+
var _this = this;
67
return _async_to_generator._(function() {
78
return _ts_generator._(this, function(_state) {
8-
if (this.msg === "") {}
9+
if (_this.msg === "") {}
910
return [
1011
2
1112
];
1213
});
13-
}).apply(this);
14+
})();
1415
}
1516
}
1617
});

crates/swc/tests/fixture/issues-1xxx/1575/case2/output/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,15 @@ var _ts_generator = require("@swc/helpers/_/_ts_generator");
33
var obj = {
44
foo: 5,
55
method: function method() {
6+
var _this = this;
67
return _async_to_generator._(function() {
78
return _ts_generator._(this, function(_state) {
89
return [
910
2,
10-
this.foo
11+
_this.foo
1112
];
1213
});
13-
}).apply(this);
14+
})();
1415
}
1516
};
1617
obj.method().then(function(v) {

crates/swc_ecma_compat_es2017/src/async_to_generator.rs

+37-39
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use swc_ecma_ast::*;
66
use swc_ecma_transforms_base::{helper, helper_expr, perf::Check};
77
use swc_ecma_transforms_macros::fast_path;
88
use swc_ecma_utils::{
9-
contains_this_expr, find_pat_ids,
9+
find_pat_ids,
1010
function::{init_this, FnEnvHoister, FnWrapperResult, FunctionWrapper},
1111
prepend_stmt, private_ident, quote_ident, ExprFactory, Remapper, StmtLike,
1212
};
@@ -339,54 +339,52 @@ impl VisitMut for Actual {
339339
return;
340340
}
341341

342-
let is_this_used = contains_this_expr(&prop.function.body);
343-
344-
let original_fn_params = prop.function.params.take();
345-
346-
let prop_method_span = prop.function.span;
347-
let prop_method_body_span = if let Some(body) = &prop.function.body {
348-
body.span
349-
} else {
350-
DUMMY_SP
342+
let Function {
343+
span,
344+
params,
345+
body: Some(body),
346+
..
347+
} = &mut *prop.function
348+
else {
349+
return;
351350
};
352-
prop.function.span = prop_method_body_span;
353351

354-
let fn_ref = make_fn_ref(
355-
Function {
356-
params: Vec::new(),
357-
..*prop.function.take()
358-
}
359-
.into(),
360-
);
352+
let span = *span;
353+
let params = params.take();
354+
let mut visitor = FnEnvHoister::new(self.unresolved_ctxt);
355+
body.visit_mut_with(&mut visitor);
361356

362-
let fn_ref = if is_this_used {
363-
fn_ref.apply(DUMMY_SP, ThisExpr { span: DUMMY_SP }.into(), Vec::new())
364-
} else {
365-
CallExpr {
366-
span: DUMMY_SP,
367-
callee: fn_ref.as_callee(),
368-
args: Vec::new(),
369-
..Default::default()
370-
}
371-
.into()
372-
};
357+
let expr = make_fn_ref(FnExpr {
358+
ident: None,
359+
function: prop.function.take(),
360+
});
373361

374362
prop.function = Function {
375-
params: original_fn_params,
376-
span: prop_method_span,
377-
is_async: false,
378-
is_generator: false,
363+
span,
364+
params,
379365
body: Some(BlockStmt {
380-
span: DUMMY_SP,
381-
stmts: vec![Stmt::Return(ReturnStmt {
382-
span: DUMMY_SP,
383-
arg: Some(Box::new(fn_ref)),
384-
})],
366+
stmts: visitor
367+
.to_stmt()
368+
.into_iter()
369+
.chain(iter::once(
370+
ReturnStmt {
371+
span: DUMMY_SP,
372+
arg: Some(
373+
CallExpr {
374+
callee: expr.as_callee(),
375+
..Default::default()
376+
}
377+
.into(),
378+
),
379+
}
380+
.into(),
381+
))
382+
.collect(),
385383
..Default::default()
386384
}),
387385
..Default::default()
388386
}
389-
.into()
387+
.into();
390388
}
391389

392390
fn visit_mut_stmts(&mut self, _n: &mut Vec<Stmt>) {}

0 commit comments

Comments
 (0)