Made function expression PIFEs to be kept. Similar to #12353 but for function expressions.
The minsize for victory is bigger because webpack's output contains many PIFEs (some shouldn't be written as PIFEs though).
refs #12353
Follow-on after #12456. Improve the test case added in that PR to make sure values are indeed based on const evaluation of the `TemplateLiteral`s, not the enum member names, by making them different from each other.
* close https://github.com/rolldown/rolldown/issues/5374
Example:
Input:
```ts
function myPropertyDecorator() {
return (target: any, propertyKey: number) => {
console.log(target.constructor.modelName, propertyKey);
};
}
class Test {
public static modelName = 'Test';
@myPropertyDecorator()
public myProperty = 1;
}
const instance = new Test();
export default instance;
```
Output diff:
```diff
function myPropertyDecorator() {
return (target, propertyKey) => {
console.log(target.constructor.modelName, propertyKey);
};
}
class Test {
constructor() {
babelHelpers.defineProperty(this, "myProperty", 1);
}
}
-babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0);
-babelHelpers.defineProperty(Test, "modelName", "Test");
+babelHelpers.defineProperty(Test, "modelName", "Test");
+babelHelpers.decorate([myPropertyDecorator()], Test.prototype, "myProperty", void 0);
const instance = new Test();
export default instance;
```
The cause is that we transform class fields and decorators in two different plugins, and the decorator plugin should be transformed first, and then run the class-properties plugin, because class-properties might erase some decorator information. However, this cause transformed decorators injected before transformed class fields.
This PR fixes this problem by collecting all transformed decorators that wait for injection, and injecting them in batch after the `class-properties` plugin has run.
* close https://github.com/rolldown/rolldown/issues/5326
Regression introduced by #12212. The transform execution shift causes the bug because the `class-properties` plugin always assumes that all fields accessed can be transformed. However, the prior change breaks the assumption.
This PR reverts some changes to remove the ts-only field early, which respects that `class-properties` assumption
close: https://github.com/oxc-project/oxc/issues/12184
I couldn't figure out where **exactly** to put tests regarding object
rest spread and arrow function transformation.
Probably somewhere underneath tasks/transform_conformance
Input:
```ts
class DeclareFields {
@dec declare name: string;
@dec declare output: number;
}
```
Before output:
```ts
class DeclareFields {}
```
After output:
```ts
class DeclareFields {}
babelHelpers.decorate([dec], DeclareFields.prototype, "name", void 0);
babelHelpers.decorate([dec], DeclareFields.prototype, "output", void 0);
```
The `declare` fields with decorators should be transformed, but they
would be removed in the typescript plugin before legacy decorators
transform them, so this PR is to adjust the transform order and allow
`declare` fields can be transformed
Related: https://github.com/oxc-project/oxc/pull/12202
`swap_remove` will swap the last element to the index you want to remove, so this will cause the expression's order to be incorrect. Here is order sensitive, so we can't use `swap_remove`.
close: #11876
This plugin adds comprehensive support for styled-components with server-side rendering, style minification, and enhanced debugging capabilities. The implementation is ported from the [official Babel plugin](https://github.com/styled-components/babel-plugin-styled-components) to ensure compatibility and feature parity.
## Current Limitations
⚠️ **Import Support**: This plugin currently only supports styled-components imported via ES modules (`import` statements). CommonJS imports using `require("styled-components")` are not yet supported.
## Feature Support
### Options:
**✅ Fully Supported:**
- `displayName`: Adds display names for debugging
- `fileName`: Controls filename prefixing in display names
- `ssr`: Adds unique component IDs for server-side rendering
- `transpileTemplateLiterals`: Converts template literals to function calls
- `minify`: Minifies CSS content in template literals
- `namespace`: Adds namespace prefixes to component IDs
- `meaninglessFileNames`: Controls which filenames are considered meaningless
**⚠️ Partially Supported:**
- `pure`: Only supports call expressions, not tagged template expressions (bundler limitation)
**❌ Not Yet Implemented:**
- `cssProp`: JSX css prop transformation
- `topLevelImportPaths`: Custom import path handling
## Testing
The test suite is adapted from the [official Babel plugin tests](https://github.com/styled-components/babel-plugin-styled-components) with modifications to integrate with our testing infrastructure.
**Note**: Some test outputs differ from the original due to our different hashing algorithm for component IDs. This is intentional and follows the same approach used by SWC's implementation.
Control printing of comments more precisely via more options:
The logic change here is that jsdoc is no longer part of annotation
comments.
```rust
pub struct CommentOptions {
/// Print normal comments that do not have special meanings.
///
/// At present only statement level comments are printed.
///
/// Default is `true`.
pub normal: bool,
/// Print jsdoc comments.
///
/// * jsdoc: `/** jsdoc */`
///
/// Default is `true`.
pub jsdoc: bool,
/// Print annotation comments.
///
/// * pure: `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`
/// * webpack: `/* webpackChunkName */`
/// * vite: `/* @vite-ignore */`
/// * coverage: `v8 ignore`, `c8 ignore`, `node:coverage`, `istanbul ignore`
///
/// Default is `true`.
pub annotation: bool,
/// Print legal comments.
///
/// * starts with `//!` or `/*!`.
/// * contains `/* @license */` or `/* @preserve */`
///
/// Default is [LegalComment::Inline].
pub legal: LegalComment,
}
```
closes#12030
related https://github.com/rolldown/tsdown/issues/357
Fixes: https://github.com/oxc-project/oxc/issues/11824
We have to introduce a visitor to pre-collect all bindings that are used in JSX elements or JSX-like calls, because a variable can be referenced before or after the declaration.
Fix `ComputedMemberExpression::static_property_name`. The value of a
template literal is the cooked version. e.g. ``obj[`\x41`]`` -> property
name `"A"` not `"\x41"`.
The only place we use this method is in React transform. Add a test for
it there.
Insert the decorations early rather than waiting for the `class` assignment to insert them together. This is to avoid the decorators being inserted before the `defineProperty(xxx)` which could cause accessing an field still doesn't decorated yet.
Input:
```ts
function Bar(): ClassDecorator {
return (_target) => {
console.log(Bar.name)
}
}
@Bar()
class Foo {
static foo = `${Foo.name}`;
}
```
Before output:
```js
var _Foo;
function Bar() {
return (_target) => {
console.log(Bar.name);
};
}
let Foo = _Foo = class Foo {};
babelHelpers.defineProperty(Foo, "foo", `${_Foo.name}`);
Foo = _Foo = babelHelpers.decorate([Bar()], Foo);
```
After output:
```js
var _Foo;
function Bar() {
return (_target) => {
console.log(Bar.name);
};
}
let Foo = _Foo = class Foo {};
Foo = _Foo = babelHelpers.decorate([Bar()], Foo);
babelHelpers.defineProperty(Foo, "foo", `${_Foo.name}`);
```
close: #11084
We don't need to transform the private field, which is part of class-properties work, so `unreachable` is expected. The bug is that we haven't skipped it.
closes#11020
Previously `SourceType::from_path(".js")` treats a `.js` file as `.jsx`
to maximize parse rate for the linter.
Force the `.jsx` change in the linter instead of a generic solution for
`SourceType::from_path`.
fixes#10948
This PR changes how comment options are interpreted.
`CodegenOptions::comments`, `CodegenOptions::annotation_comments` and
`CodegenOptions::legal_comments` are now independent of each other.
### `CodegenOptions::comments`
Controls printing of normal comments. At present, only some leading
comments are preserved. It does not control legal and annotation
comments.
### `CodegenOptions::annotation_comments`
Controls printing of annotation comments
* jsdoc: `/** jsdoc */`
* pure: `/* #__PURE__ */` and `/* #__NO_SIDE_EFFECTS__ */`
* webpack: `/* webpackChunkName */`
* vite: `/* @vite-ignore */`
* coverage: `v8 ignore`, `c8 ignore`, `node:coverage`, `istanbul ignore`
### `CodegenOptions::legal_comments`
Controls printing of legal comments
* starts with `//!` or `/*!`.
* contains `/* @license */` or `/* @preserve */`
---
Comment generation is also changed:
codegen first builds a comments map by keeping only the needed comments.
Printing functions will then print out comments in their respective
positions.
---
This PR reveals some incorrect comment interpretation:
* https://github.com/oxc-project/oxc/issues/10998
> [!NOTE]
> The explanation in the comment is incorrect because the `h` function
might be locally defined rather than imported. Removing the conditional
check will fix the issue.
- Closes: #10956
Co-authored-by: Dunqing <dengqing0821@gmail.com>
fixes#10839
```
class Foo {
#name: string;
f() { #name in other && this.#name === other.#name }
^^^^^ rhs is only this part
}
RelationalExpression[In, Yield, Await] :
[+In] PrivateIdentifier in ShiftExpression[?Yield, ?Await]
```
Alter the algorithm for generating UIDs, to improve its performance.
Previously we stored all existing symbol names which start with `_` in an `FxHashSet`. When creating a UID based on `foo`, it would first see if `_foo` is available, then try `_foo2`, then `_foo3`, then `_foo4` etc.
When creating a lot of UIDs from the same base name (`foo` in example above), this has poor performance as each attempt requires a separate hashset lookup.
Instead, use an `FxHashMap` mapping base name to:
1. Largest number of underscores at start.
2. Largest numeric prefix on end.
i.e. if there are existing symbols `_foo`, `_bar3`, `_bar8`, `_qux`, `___qux2`, this produces a map:
```
{
"foo": { postfix: 1, underscore_count: 1 },
"bar": { postfix: 8, underscore_count: 1 },
"qux": { postfix: 2, underscore_count: 3 },
}
```
When generating a UID, `postfix` is incremented and UID is constructed as `<underscores><base><postfix>`.
This requires a maximum of 1 x hashmap lookup and 1 x hashmap insert for each UID. It also reduces the size of the hashmap where many UIDs are created for same base name.
This new algorithm produces almost same UIDs as Babel, but not quite. 3 tests require their outputs to be changed due to UIDs being different.