Skip to content

Commit

Permalink
fix(es/transforms/compat): Apply regenerator for default function d…
Browse files Browse the repository at this point in the history
…eclarations (#2681)

swc_ecma_transforms_compat:
 - `regenerator`: Handle `DefaultDecl::Fn`. (Closes #2677)
  • Loading branch information
kwonoj authored Nov 9, 2021
1 parent 9824fda commit 8fe0d25
Show file tree
Hide file tree
Showing 2 changed files with 163 additions and 0 deletions.
29 changes: 29 additions & 0 deletions ecmascript/transforms/compat/src/es2017/async_to_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,35 @@ impl Fold for Actual {
}
}

fn fold_module_item(&mut self, item: ModuleItem) -> ModuleItem {
match item {
// if fn is ExportDefaultDecl, fn is not FnDecl but FnExpr
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(export_default)) => {
if let DefaultDecl::Fn(expr) = export_default.decl {
let expr = if !expr.function.is_async {
expr
} else {
let function = self.fold_fn(expr.ident.clone(), expr.function, true);
FnExpr {
ident: expr.ident,
function,
}
};

ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(ExportDefaultDecl {
decl: expr.into(),
..export_default
}))
} else {
let item =
ModuleItem::ModuleDecl(ModuleDecl::ExportDefaultDecl(export_default));
item.fold_children_with(self)
}
}
_ => item.fold_children_with(self),
}
}

fn fold_method_prop(&mut self, prop: MethodProp) -> MethodProp {
let prop = prop.fold_children_with(self);

Expand Down
134 changes: 134 additions & 0 deletions ecmascript/transforms/compat/tests/es2017_async_to_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2883,6 +2883,140 @@ myclass.handle();
"
);

test!(
Syntax::default(),
|_| {
let top_level_mark = Mark::fresh(Mark::root());
chain!(
async_to_generator(),
regenerator(Default::default(), top_level_mark)
)
},
issue_2677_1,
"
async function region() {
}
export async function otherCall() {
await region();
}
export default async function someCall() {
await region();
}
",
"
var regeneratorRuntime = require('regenerator-runtime');
function _region() {
_region = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_ctx) {
while(1)switch(_ctx.prev = _ctx.next){
case 0:
case 'end':
return _ctx.stop();
}
}, _callee);
}));
return _region.apply(this, arguments);
}
function region() {
return _region.apply(this, arguments);
}
function _otherCall() {
_otherCall = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_ctx) {
while(1)switch(_ctx.prev = _ctx.next){
case 0:
_ctx.next = 2;
return region();
case 2:
case 'end':
return _ctx.stop();
}
}, _callee);
}));
return _otherCall.apply(this, arguments);
}
export function otherCall() {
return _otherCall.apply(this, arguments);
}
function _someCall() {
_someCall = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_ctx) {
while(1)switch(_ctx.prev = _ctx.next){
case 0:
_ctx.next = 2;
return region();
case 2:
case 'end':
return _ctx.stop();
}
}, _callee);
}));
return _someCall.apply(this, arguments);
}
export default function someCall() {
return _someCall.apply(this, arguments);
}
"
);

test!(
Syntax::default(),
|_| {
let top_level_mark = Mark::fresh(Mark::root());
chain!(
async_to_generator(),
regenerator(Default::default(), top_level_mark)
)
},
issue_2677_2,
"
async function region() {
}
export default async function() {
await region();
}
",
"
var regeneratorRuntime = require('regenerator-runtime');
function _region() {
_region = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_ctx) {
while(1)switch(_ctx.prev = _ctx.next){
case 0:
case 'end':
return _ctx.stop();
}
}, _callee);
}));
return _region.apply(this, arguments);
}
function region() {
return _region.apply(this, arguments);
}
function _ref() {
_ref = _asyncToGenerator(regeneratorRuntime.mark(function _callee() {
return regeneratorRuntime.wrap(function _callee$(_ctx) {
while(1)switch(_ctx.prev = _ctx.next){
case 0:
_ctx.next = 2;
return region();
case 2:
case 'end':
return _ctx.stop();
}
}, _callee);
}));
return _ref.apply(this, arguments);
}
export default function() {
return _ref.apply(this, arguments);
}
"
);

#[testing::fixture("tests/fixture/async-to-generator/**/exec.js")]
fn exec(input: PathBuf) {
let input = read_to_string(&input).unwrap();
Expand Down

0 comments on commit 8fe0d25

Please sign in to comment.