Skip to content

Commit

Permalink
feat(transformer): complete the async-to-generator plugin (oxc-projec…
Browse files Browse the repository at this point in the history
…t#6658)

In this PR, most of the async functions have transformed correctly. But the async arrow functions don't fully transform correctly yet, it is related to we need to transform the arrow function to the generator function. For example:

Input:
```js
function declaration() {
  const asy = async () => {
  console.log(this.name)
 }
}
```

Output:
```js
function declaration() {
  const asy = babelHelpers.asyncToGenerator(function* () {
     console.log(this.name);
  });
}
```

Expected Output:

```js
function declaration() {
  var _this = this;
  const asy = /*#__PURE__*/function () {
    var _ref = babelHelpers.asyncToGenerator(function* () {
      console.log(_this.name);
    });
    return function asy() {
      return _ref.apply(this, arguments);
    };
  }();
}
```

From the expected output, we haven't handled `this` correctly, which means even if the `arrow-function` plugin doesn't enable, we still need to handle this correctly as the `arrow-function` plugin does, and further question if `arrow-function` plugin is enabled, how to avoid these making conflict?

I thought we may move out the implementation of `arrow-function` and as a common helper, this way every plugin can handle this well
  • Loading branch information
Dunqing committed Oct 25, 2024
1 parent fcc6221 commit 0d0bb17
Show file tree
Hide file tree
Showing 21 changed files with 765 additions and 170 deletions.
39 changes: 39 additions & 0 deletions crates/oxc_ast/src/ast_builder_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,45 @@ impl<'a> AstBuilder<'a> {
mem::replace(decl, empty_decl)
}

/// Move a formal parameters out by replacing it with an empty [`FormalParameters`].
#[inline]
pub fn move_formal_parameters(self, params: &mut FormalParameters<'a>) -> FormalParameters<'a> {
let empty_params = self.formal_parameters(Span::default(), params.kind, self.vec(), NONE);
mem::replace(params, empty_params)
}

/// Move a function body out by replacing it with an empty [`FunctionBody`].
#[inline]
pub fn move_function_body(self, body: &mut FunctionBody<'a>) -> FunctionBody<'a> {
let empty_body = self.function_body(Span::default(), self.vec(), self.vec());
mem::replace(body, empty_body)
}

/// Move a function out by replacing it with an empty [`Function`]
#[inline]
pub fn move_function(self, function: &mut Function<'a>) -> Function<'a> {
let params = self.formal_parameters(
Span::default(),
FormalParameterKind::FormalParameter,
self.vec(),
NONE,
);
let empty_function = self.function(
FunctionType::FunctionDeclaration,
Span::default(),
None,
false,
false,
false,
NONE,
NONE,
params,
NONE,
NONE,
);
mem::replace(function, empty_function)
}

/// Move an array element out by replacing it with an
/// [elision](ArrayExpressionElement::Elision).
pub fn move_array_expression_element(
Expand Down
1 change: 0 additions & 1 deletion crates/oxc_transformer/src/common/statement_injector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ impl<'a> StatementInjectorStore<'a> {
}

/// Add a statement to be inserted immediately after the target statement.
#[expect(dead_code)]
pub fn insert_after(&self, target: &Statement<'a>, stmt: Statement<'a>) {
let mut insertions = self.insertions.borrow_mut();
let adjacent_stmts = insertions.entry(target.address()).or_default();
Expand Down
Loading

0 comments on commit 0d0bb17

Please sign in to comment.