Fully support transforming ChainExpression in class properties. Our implementation has some differences in execution order compared to Babel, but we have passed all execution-related tests.
Similar to #7516. Fix class properties transform to replace references to class name in static prop initializers with temp var.
Input:
```js
class C {
static getSelf = () => C;
}
const C2 = C;
C = 123;
assert(C2.getSelf() === C);
```
Output:
```js
var _C;
class C {}
_C = C;
_defineProperty(C, "getSelf", () => _C);
const C2 = C;
C = 123;
assert(C2.getSelf() === C);
```
Previously, temp var wasn't used so code was `_defineProperty(C, "getSelf", () => C);`. `C` is altered later by `C = 123`, so `C2.getSelf()` returned `123`, instead of reference to the class.
Fix class properties transform to create a temp var for class when it's required.
Input:
```js
class C {
static getSelf = () => this;
}
const C2 = C;
C = 123;
assert(C2.getSelf() === C);
```
Output:
```js
var _C;
class C {}
_C = C;
_defineProperty(C, "getSelf", () => _C);
const C2 = C;
C = 123;
assert(C2.getSelf() === C);
```
Previously, temp var wasn't used so code was `_defineProperty(C, "getSelf", () => C);`. `C` is altered later by `C = 123`, so `C2.getSelf()` returned `123`, instead of reference to the class.
The logic around when a temp var is required and when it's not, and when/where it's referenced is ridiculously complicated. So add some debug assert mechanisms to double-check the logic.
Small optimization. Move code out of the loop which determines if class property transform has nothing to do and can bail out early. This also clears the way for correcting the logic around when temp vars are/aren't created in #7516.
Script to update fixtures for class properties transform was failing to transform fixtures where output is `output.mjs` (instead of `output.js`). This PR fixes that.
Transform private property accesses in static prop initializers. e.g.:
Input:
```js
class C {
static #x = 123;
static y = this.#x;
}
```
Transformed:
```js
class C {}
var _x = { _: 123 };
babelHelpers.defineProperty(C, "y", babelHelpers.assertClassBrand(C, C, _x)._);
```
`this.#x` has been transformed to `babelHelpers.assertClassBrand(C, C, _x)._`.
Add class properties transform.
Implementation is incomplete. Notable missing parts:
* Scopes are not updated where property initializers move from class body into class constructor / `_super` function.
* Does not handle binding shadowing problems when property initializers move from class body into class constructor.
* `this` and references to class name in static property initializers need to be transformed to point to a temp var.
* Not all usages of private properties are supported (see below).
* Code which is moved to outside of class body is not transformed by other transforms for class declarations (works OK for class expressions). This includes static property initializers, static blocks, and computed property/method keys.
* Only basic checks for whether computed property/method keys may have side effects.
* Numerous other small issues noted in TODO comments through the code.
### Private properties
Currently does not handle the following usages of private properties:
```js
class Class {
#prop;
static #static;
method() {
object?.#prop;
object?.#prop();
[object.#prop] = [1];
({x: object.#prop} = {x: 1});
object.#prop`xyz`;
object?.#static;
object?.#static();
[object.#static] = [1];
({x: object.#static} = {x: 1});
object.#static`xyz`;
}
}
```
close: #7338close: #7344
The `SymbolFlags::Export` is Initially used to solve `ExportSpecifier` that is not `IdentifierReference` that causes we cannot determine whether a Binding is not used everywhere by `Semantic`.
Since #3820 this problem is solved, so we don't need `SymbolFlags::Export` no longer. Also, removing this can help us easier to pass the `Semantic` check in `Transformer`
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
After transformation, super expressions have moved to unexpected places. This PR replaces super expression to call expression, and then inserts the super methods to the top of the method body.
For example:
Before:
```js
class G {
async method() {
super.foo()
}
}
```
After:
```js
class G {
method() {
var _superprop_getFoo = () => super.foo,
_this = this;
return _asyncToGenerator(function* () {
_superprop_getFoo().call(_this);
})();
}
}```
Support for inferring function name from ObjectPropertyValue's key
For example:
```js
({ foo: async function() {} })
```
After this, we will able to infer `foo` for the object method
The scope can be moved or deleted, we need to check whether the scope id is the same as the container's scope id, if not, we need to move the `this_var` to the target scope id.
Part of https://github.com/oxc-project/oxc/pull/7074
In async-to-generator and async-generator-functions plugins, we may need to transform the async arrow function to a regular generator function, now we can reuse the ability of the ArrowFunction plugin by enabling `ArrowFunctionConverter`.
I will fix semantic errors in the follow-up PR
Part of #7074
We need to handle this before the `arrow_function` plugin inserts `_this = this` because, in the `async-to-generator` plugin, we will move the body to an inner generator function. However, we don't want `_this = this` moved to the inner generator function as well. So as long as we move first, and then insert, we can fix this problem.
The new semantic error is related to another tricky problem, I will fix it in another PR