Commit graph

46 commits

Author SHA1 Message Date
Boshen
7f4b302508
chore: vitest 3.0.0 (#8578) 2025-01-18 12:10:01 +08:00
overlookmotel
cfd783aa19
chore(coverage): bump babel submodule (#8508)
Update babel submodule for conformance tests to latest HEAD.

The test fixtures include a new one for a bug fix which @branchseer
intends to also apply to Oxc - https://github.com/babel/babel/pull/17050
(see #8342).
2025-01-15 22:58:15 +08:00
overlookmotel
ca02c16f8f test(transformer): handle more exec tests (#8493)
Some of Babel's exec tests contain a return statement at top level, in order to return a Promise.

e.g. ad572fd1a1/packages/babel-plugin-transform-private-methods/test/fixtures/private-method-loose/async/exec.js

These test files could not be parsed due to illegal position of `return`, and the tests were silently excluded.

This PR:

1. Includes those tests by passing `allow_return_outside_function: true` option to parser for exec tests.
2. Includes a "transform error" message in snapshot for any exec tests which produce errors in parser/transformer.
2025-01-15 02:07:04 +00:00
Dunqing
0592a8b43f feat(transformer/class-properties): transform private in expression (#8202)
This PR support transforms `#prop in object` in class-properties to cover https://www.npmjs.com/package/@babel/plugin-transform-private-property-in-object  plugin does
2024-12-31 12:30:58 +00:00
Dunqing
80c16526fb chore(transformer): enable Babel's private-property-in-property plugin tests (#8201) 2024-12-31 12:30:57 +00:00
Dunqing
ad77ad5c12 feat(transformer/class-properties): transform static/instance accessor methods (#8132)
This PR supports transforming private `getter` or `setter` methods, and the output is a little different from Babel's output, For example:

Input:
```js
class Cls {
  #prop = 0;

  get #accessor() {
    return this.#prop;
  }
  set #accessor(v) {
    console.log(arguments);
    this.#prop = v;
  }

  constructor() {
    console.log(this.#accessor)
    [this.#accessor] = [1];
  }
}
```

[Babel's output](https://babeljs.io/repl#?browsers=defaults%2C%20not%20ie%2011%2C%20not%20ie_mob%2011&build=&builtIns=false&corejs=3.21&spec=false&loose=false&code_lz=MYGwhgzhAEDCIwN4ChrQMQAcBOB7T0AvNAAwDcyq0A5gKYAuGYwwtUu2AFAJTQpppsDAK7YAdtHoALAJYQAdFjyYKaAL5UIDJizYQOnAG69-A4LjH6QteSFzVOYbNWEBbWmPoRuqgdLmKOPhE0Ia-GlTmlvTYwsD0BiZUaFFWNnYO_grozKzs2NzJ0ADaWYq5ehwAuiHFAIxV4cgaQA&debug=false&forceAllTransforms=false&modules=false&shippedProposals=false&evaluate=false&fileSize=false&timeTravel=false&sourceType=script&lineWrap=true&presets=&prettier=false&targets=&version=7.26.4&externalPlugins=%40babel%2Fplugin-transform-class-properties%407.25.9%2C%40babel%2Fplugin-transform-private-methods%407.25.9%2C%40babel%2Fplugin-external-helpers%407.25.9&assumptions=%7B%7D):
```js
var _prop = new WeakMap();
var _Cls_brand = new WeakSet();
class Cls {
  constructor() {
    babelHelpers.classPrivateMethodInitSpec(this, _Cls_brand);
    babelHelpers.classPrivateFieldInitSpec(this, _prop, 0);
    console.log(babelHelpers.classPrivateGetter(_Cls_brand, this, _get_accessor));
    [babelHelpers.classPrivateGetter(_Cls_brand, this, _get_accessor)] = [1];
  }
}
function _get_accessor(_this) {
  return babelHelpers.classPrivateFieldGet(_prop, _this);
}
function _set_accessor(_this2, v) {
  var _arguments = [].slice.call(arguments, 1);
  console.log(_arguments);
  babelHelpers.classPrivateFieldSet(_prop, _this2, v);
}
```

Oxc's output:
```js
var _prop = new WeakMap();
var _Cls_brand = new WeakSet();
class Cls {
        constructor() {
                babelHelpers.classPrivateMethodInitSpec(this, _Cls_brand);
                babelHelpers.classPrivateFieldInitSpec(this, _prop, 0);
                console.log(_get_accessor.call(babelHelpers.assertClassBrand(_Cls_brand, this)));
                [babelHelpers.toSetter(_set_accessor.bind(babelHelpers.assertClassBrand(_Cls_brand, this)), [])._] = [1];
        }
}
function _get_accessor() {
        return babelHelpers.classPrivateFieldGet2(_prop, this);
}
function _set_accessor(v) {
        console.log(arguments);
        babelHelpers.classPrivateFieldSet2(_prop, this, v);
}
```

### Main difference
```diff
// Babel
+ console.log(babelHelpers.classPrivateGetter(_Cls_brand, this, _get_accessor));
+ [babelHelpers.classPrivateGetter(_Cls_brand, this, _get_accessor)] = [1];

+ function _get_accessor(_this) {
+   return babelHelpers.classPrivateFieldGet(_prop, _this);
+ }

+ function _set_accessor(_this2, v) {
+   var _arguments = [].slice.call(arguments, 1);
+   console.log(_arguments);
+   babelHelpers.classPrivateFieldSet(_prop, _this2, v);
+ }

// Oxc
-  console.log(_get_accessor.call(babelHelpers.assertClassBrand(_Cls_brand, this)));- -
-  [babelHelpers.toSetter(_set_accessor.bind(babelHelpers.assertClassBrand(_Cls_brand, this)), [])._] = [1];

- function _get_accessor() {
-   return babelHelpers.classPrivateFieldGet2(_prop, this);
- }

- function _set_accessor(v) {
-   console.log(arguments);
-   babelHelpers.classPrivateFieldSet2(_prop, this, v);
- }
```

From the main differences, we can see that Babel handles `getter` and `setter` methods using `classPrivateGetter` and `classPrivateSetter` helper functions, which causes all use `this` and `arguments` needs to rewrite to use a temp var instead in `getter` and `setter` methods. This is unnecessary and is not an efficient transformation for us.

Instead, I adapt binding a `this` instead of passing in `this`, this way we don't need to rewrite anything. We can't control the `helper` library for now, so I just transformed the AST to bind `this`, in the future, we can create a helper function to do the same thing.
2024-12-31 12:30:56 +00:00
Dunqing
e405f79577 feat(transformer/class-properties): transform static private method invoking (#8117) 2024-12-31 12:30:56 +00:00
Dunqing
3303e9986b feat(transformer/class-properties): insert statements after statement of class expression (#8116) 2024-12-31 12:30:55 +00:00
Dunqing
0cc71cf5e3 feat(transformer/class-properties): transform super expressions and identifiers that refers to class binding in private method (#8106)
All private methods will be moved out of class, so we need to transform all `super` expressions in private methods and transform identifiers that refer to class binding.
2024-12-31 12:30:55 +00:00
Dunqing
58ed83242a feat(transformer/class-properties): transform private field expression which invokes private method (#8102) 2024-12-31 12:30:53 +00:00
Dunqing
f14567a658 feat(transformer/class-properties): transform callee which invokes private method (#8100)
transform call expression's callee if it invokes a private method
2024-12-31 12:30:52 +00:00
Dunqing
13349ef1b8 feat(transformer/class-properties): transform private methods (#8099)
This PR support transforms private methods in a class, moving all of them to after the `class`
2024-12-31 12:30:52 +00:00
Dunqing
6af5870a7d chore(transformer): enable Babel's private-methods plugin tests (#8098)
part of #8052
2024-12-31 12:30:51 +00:00
overlookmotel
273795d471 fix(transformer/class-properties): run other transforms on static properties, static blocks, and computed keys (#7982)
Large re-architecting of class properties transform. Split transform into 3 phases:

1. Transform instance properties when entering class.
2. Transform private fields during traversal of class body.
3. Transform static properties and static blocks when exiting class.

This ensures that code which has to be moved outside of the class (static property initializers, static blocks, computed keys) can get transformed by other transforms before they're moved out.

Also fixes a problem where we previously registered private properties too early - on entering the class, rather than the class *body*, so private fields in `extends` clause of a nested class were misinterpretted.
2024-12-20 10:07:23 +00:00
overlookmotel
e76fbb0721 fix(transformer/class-properties): fix symbol clashes in instance prop initializers (#7872)
Instance property initializers are moved into constructor. If symbols they reference are shadowed within constructor, rename those symbols.

Input:

```js
class C {
  prop = foo();
  constructor(foo) {
    console.log(foo);
  }
}
```

Output:

```js
class C {
  constructor(_foo) { // <-- renamed
    this.prop = foo(); // <-- moved into constructor
    console.log(_foo); // <-- renamed
  }
}
```
2024-12-15 01:53:12 +00:00
Dunqing
e727ae9698 feat(transformer/class-properties): transform super member expressions that are inside static prop initializer (#7815)
This PR support for transforming `super.prop` to  `babelHelpers.superPropGet(_B, "prop", _B)`

Input:
```js
class A {
  static prop = 1;
}

class B extends A {
  static prop = 2;
  static propA = super.prop;
  static getPropA = () => super.prop;
}
```

Output:
```js
var _B;
class A {}
babelHelpers.defineProperty(A, "prop", 1);
class B extends A {}
_B = B;
babelHelpers.defineProperty(B, "prop", 2);
babelHelpers.defineProperty(B, "propA", babelHelpers.superPropGet(_B, "prop", _B));
babelHelpers.defineProperty(B, "getPropA", () => babelHelpers.superPropGet(_B, "prop", _B));
```
2024-12-13 02:33:37 +00:00
overlookmotel
2e69720ba0 feat(transformer/class-properties): support private_fields_as_properties assumption (#7717)
Support `private_fields_as_properties` assumption in class properties transform. This assumption is also enabled by the transform's `loose` option.

Optional chain (e.g. `this?.#prop`) is not yet implemented, but all other usages of private fields are supported. We'll handle optional chain in a follow-on PR.
2024-12-10 02:28:31 +00:00
overlookmotel
5fd136139f test(transformer/class-properties): override fixtures (#7689)
Override some transform conformance test fixtures for class properties transform, where:

* Our output differs from Babel in cosmetic manner only.
* Our transform intentionally works differently from Babel.
* Babel's fixtures enable arrow functions transform, which malfunctions in our implementation. But we're not trying to test arrow functions transform here, so disable it.
2024-12-08 01:41:33 +00:00
overlookmotel
65a1c311ab test(transformer): fix exec test reporter (#7722)
`JsonReporter` which the custom test reporter introduced in #7715 uses does not provide error message in `message` prop, where cause of failure is failing assertions. So tests failing due to failing assertions were omitted from snapshot. Include them.

Also add count of passing tests at top of the snapshot.
2024-12-08 01:41:30 +00:00
Boshen
5891166c80 feat(transform_conformance): custom reporter for exec test (#7715)
closes #7704
2024-12-07 11:25:00 +00:00
Dunqing
86d4c90e4d feat(transformer/class-properties): support for transforming AssignmentTarget (#7697)
Instance prop:
 * `[object.#prop] = arr` -> `[_toSetter(_classPrivateFieldSet, [_prop, object])._] = arr`
 * `({x: object.#prop} = obj)` -> `({ x: _toSetter(_classPrivateFieldSet, [_prop, object])._ } = obj)`

 Static prop:
 * `[object.#prop] = arr` -> `[_assertClassBrand(Class, object, _prop)._] = arr`
 * `({x: object.#prop} = obj)` -> `({ x: _assertClassBrand(Class, object, _prop)._ } = obj)`
2024-12-06 12:18:54 +00:00
Boshen
c3a538c47c
deps: node v22.12.0 (#7693) 2024-12-06 13:59:37 +08:00
Dunqing
c793d71a78 feat(transformer/class-properties): transform ChainExpression (#7575)
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.
2024-12-04 16:52:57 +00:00
overlookmotel
eb825edee2 fix(transformer/class-properties): replace references to class name with temp var in static prop initializers (#7610)
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.
2024-12-03 12:43:21 +00:00
overlookmotel
0eadd9f6de fix(transformer/class-properties): create temp var for class where required (#7516)
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.
2024-12-03 07:46:04 +00:00
Boshen
bf16668de7 feat(transform_conformance): keep exec snapshot files (#7565)
closes #7564
2024-12-01 10:13:47 +00:00
Dunqing
3539f56cac feat(transformer/class-properties): support for transforming TaggedTemplateExpresssion (#7504)
```js
"object.#prop`xyz`" -> "_classPrivateFieldGet(_prop, object).bind(object)`xyz`"
"object.obj.#prop`xyz`" -> "_classPrivateFieldGet(_prop, _object$obj = object.obj).bind(_object$obj)`xyz`"
```
2024-11-27 12:15:31 +00:00
overlookmotel
199076bd14 fix(transformer/class-properties): transform private property accesses in static prop initializers (#7483)
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)._`.
2024-11-26 11:36:09 +00:00
overlookmotel
97de0b7be1 fix(transformer/class-properties): transform this in static prop initializers (#7481)
Convert `this` in static property initializers to reference to class name.

`class C { static prop = this; }` -> `class C {}; C.prop = C;`
2024-11-25 20:10:05 +00:00
overlookmotel
9778298fdb feat(transformer): class properties transform (#7011)
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`;
  }
}
```
2024-11-25 10:24:20 +00:00
Boshen
6f161de10f chore(coverage): bump test262, babel and TypeScript submodules (#7452) 2024-11-24 16:26:45 +00:00
Boshen
885e37f8eb feat(transformer): Optional Chaining (#6990)
close: #6958
2024-11-21 03:12:18 +00:00
renovate[bot]
b3965bbff0
chore(deps): update npm packages (#7364) 2024-11-20 17:26:48 +08:00
Boshen
d60801218e feat(transform_conformance): snapshot our transformed outputs (#7358) 2024-11-19 12:49:44 +00:00
Boshen
84f3bf2f97 refactor(transform_conformance): clean up test execution code (#7357) 2024-11-19 12:22:42 +00:00
renovate
3da9443b0e chore(deps): update dependency @types/node to v22.9.0 (#7145)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node)) | [`22.8.4` -> `22.9.0`](https://renovatebot.com/diffs/npm/@types%2fnode/22.8.4/22.9.0) | [![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.8.4/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.8.4/22.9.0?slim=true)](https://docs.renovatebot.com/merge-confidence/) |

---

### Configuration

📅 **Schedule**: Branch creation - "before 10am on monday" in timezone Asia/Shanghai, Automerge - At any time (no schedule defined).

🚦 **Automerge**: Enabled.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/oxc-project/oxc).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOC4xNDIuNyIsInVwZGF0ZWRJblZlciI6IjM4LjE0Mi43IiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->
2024-11-06 06:17:36 +00:00
Dunqing
df772411ea feat(transformer): enable ArrowFunctionConverter in async-to-generator and async-generator-functions plugins (#7113)
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
2024-11-06 03:02:36 +00:00
Boshen
9386435efb
feat(transform_conformance): use node instead of bun for exec tests (#7121) 2024-11-05 14:20:48 +08:00
Boshen
c2802e63fc feat(transform_conformance): add babel runtime to exec tests (#7114) 2024-11-04 14:38:15 +00:00
Dunqing
934cb5e746 feat(transformer): add async_generator_functions plugin (#6573)
Passed 15/19 tests. The remaining 4 failed tests related to `this` expression, the problem same as I mentioned in #6658. I will fix them in follow-up PRs.
2024-10-31 09:14:17 +00:00
overlookmotel
10484cdeeb feat(transformer): class static block transform (#6733)
Add ES2022 class static block transform.
2024-10-22 03:40:02 +00:00
Boshen
3711c32f22 chore(coverage): bump test262, babel and TypeScript (#6702)
closes #6692
2024-10-20 15:02:26 +00:00
Dunqing
a3dea9c542 feat(transformer/async-to-generator): handle arrow-function correctly (#6640) 2024-10-17 08:47:28 +00:00
Dunqing
673b66620b chore(transform_conformance): do not extend plugins if current options has plugins (#6627)
I saw many tests were ignored even if they don't contain any unsupported plugins
2024-10-17 02:07:03 +00:00
Ethan Goh
a9260cf6d1
feat(transformer): async-to-generator plugin. (#5590)
Tests are still not passed. A lot need to do yet.

---------

Co-authored-by: Dunqing <dengqing0821@gmail.com>
2024-10-14 17:16:58 +08:00
overlookmotel
9dac6dfb23 test(transformer): move transformer conformance snapshots into separate directory (#5917)
Move snapshots for transform conformance into a `snapshots` sub-folder.
2024-09-20 10:25:17 +00:00
Renamed from tasks/transform_conformance/babel_exec.snap.md (Browse further)